python - Python unittest模拟类和类方法
问题描述
我觉得这可能相对简单,但我正在拔头发来让它工作。我想模拟整个类,然后指定此类方法之一的返回值。
我已经看过这里,其他几个问题,当然还有文档。我仍然无法让它工作。请看下面我的简单示例。
目录内容tmp
:
tmp
├── __init__.py
├── my_module.py
└── test_my_module.py
内容my_module.py
:
class MyClass:
def __init__(self):
# Do expensive operations that will be mocked in testing.
self.a = 7
def my_method(self):
# For sake of simple example, always return 1.
return 1
def create_class_call_method():
"""Create MyClass instance and call its my_method method, returning
the result."""
instance = MyClass()
value = instance.my_method()
return value
内容test_my_module.py
:
import unittest
from unittest.mock import patch, Mock
from tmp import my_module
class MyClassTestCase(unittest.TestCase):
def test_create_class_call_method(self):
# Attempt to patch MyClass as well as specify a return_value for
# the my_method method (spoiler: this doesn't work)
with patch('tmp.my_module.MyClass',
my_method=Mock(return_value=2)):
value = my_module.create_class_call_method()
self.assertEqual(value, 2)
if __name__ == '__main__':
unittest.main()
运行结果test_my_module.py
:
2 != <MagicMock name='MyClass().my_method()' id='140234477124048'>
Expected :<MagicMock name='MyClass().my_method()' id='140234477124048'>
Actual :2
我尝试过的其他一些事情:
- 而不是
..., my_method=Mock(return_value=2))
在patch
语句中,解压缩字典,如下所示:**{'my_method.return_value': 2}
- 嵌套
with patch
语句。外部语句很简单 likewith patch('tmp.my_module.MyClass'):
,内部语句尝试my_method
像这样进行修补:with patch('tmp.my_module.MyClass.my_method, return_value=2)
- 使用补丁装饰器而不是上下文管理器
- 将补丁语句更改为
with patch('tmp.my_module.MyClass') as p:
然后在with
语句内部,尝试p
像这样设置:p.evaluate = Mock(return_value=2)
任何帮助表示赞赏,谢谢。
解决方案
我找到了一个更好的解决方案。总之,我们需要mock出return_value
mock MyClass
。这是工作测试代码:
import unittest
from unittest.mock import patch, Mock, MagicMock
from tmp import my_module
class MyClassTestCase(unittest.TestCase):
def test_create_class_call_method(self):
# Create a mock to return for MyClass.
m = MagicMock()
# Patch my_method's return value.
m.my_method = Mock(return_value=2)
# Patch MyClass. Here, we could use autospec=True for more
# complex classes.
with patch('tmp.my_module.MyClass', return_value=m) as p:
value = my_module.create_class_call_method()
# Method should be called once.
p.assert_called_once()
# In the original my_method, we would get a return value of 1.
# However, if we successfully patched it, we'll get a return
# value of 2.
self.assertEqual(value, 2)
if __name__ == '__main__':
unittest.main()
以及成功的结果:
Ran 1 test in 0.002s
OK
推荐阅读
- sql - 合并日期时间范围 Oracle SQL 或 PL/SQL
- python - 在考虑该列表的不同顺序的同时操作列表 - python 2
- python-3.x - 在 python 中使用正则表达式从转换后的稀疏向量列表中删除离散值的问题
- mysql - 尝试将 API 信息从 python 转储到 mySQL
- html - 在 CSS 中使用伪元素将内容推送到元素的左侧、右侧、顶部或底部
- mysql - SQLSTATE[HY000] [2006] MySQL 服务器已经消失 laravel mysql 和 xampp
- docker - Traefik 根本没有加载我的配置文件
- matlab - 是否可以实时从 MATLAB 函数向 Simulink 提供值?
- angular - Angular 9 rxJs - 如何使用组合/合并语句来检索可观察值并传递给另一个函数
- javascript - 验证数字 1、2 和 3 时出现问题