如何解决使用unittest.mock模拟类中使用的模块需要哪个目标?
我需要创建一个模块作用域的夹具,在其中模拟module_a
中使用的module_c
和module_b.Module_B_Class()
。我无法使用嘲笑.patch批注,因为它提供了函数范围的嘲笑,并且我还需要断言,在调用Module_B_Class
时,在module_a
上会调用一个特定的函数,而在{{1 }}。因此,我使用了pytest-cases unpack_into功能并编写了以下代码:
module_c
但是,当我运行以下命令时:
@pytest_cases.fixture_plus(scope="module",unpack_into="mocked_module_a,mocked_module_b")
def my_fixture():
with mock.patch('my_top_module.my_sub_module.module_b.module_a') as module_a_mock:
with mock.patch('my_top_module.my_sub_module.module_b.module_c') as module_c_mock:
module_a_mock.my_func = MagicMock(return_value='Hello world')
module_c_mock.my_func_2 = MagicMock(return_value='Good morning')
这样定义
def test_my_class(mocked_module_a,mocked_module_b):
my_class = Module_B_Class()
my_class.run()
mocked_module_a.assert_called_once()
mocked_module_b.assert_called_once()
被调用的函数是原始函数,而不是替换的函数。我打错的目标是错误的吗?
解决方法
夹具在pytest documentation中进行了描述。基本原理是yield
之前的代码在测试之前(或根据范围,在第一个测试之前,每个模块或每个测试类)和yield
之后的代码执行在测试(或最后一个测试,模块或类)之后执行:
@pytest.fixture
def my_fixture():
do_setup()
yield
do_teardown()
您当然也可以使用yield
返回一个值。
对于上下文管理器而言,这意味着您必须在超出范围之前屈服:
@pytest.fixture(scope="module")
def my_fixture():
with mock.patch('my_top_module.my_sub_module.module_b.module_a') as module_a_mock:
module_a_mock.my_func = MagicMock(return_value='Hello world')
yield module_a_mock
如果需要,您现在可以通过测试中的装置名称访问该模拟。在这种情况下,仅在执行当前模块中的测试之后,代码才在yield
之后返回,因此此时将还原补丁。
如果在这种情况下不执行yield
,则在执行夹具时会立即超出范围,这意味着补丁会在进行测试之前恢复。
更新:
以下是使用pytest_cases
的更新问题的版本:
@pytest_cases.fixture_plus(scope="module",unpack_into="mocked_module_a,mocked_module_c")
def my_fixture():
with mock.patch(
'my_top_module.my_sub_module.module_b.module_a') as module_a_mock:
with mock.patch(
'my_top_module.my_sub_module.module_b.module_c') as module_c_mock:
module_a_mock.my_func = mock.MagicMock(return_value='Hello world')
module_c_mock.my_func2 = mock.MagicMock(return_value='Good morning')
yield (module_a_mock,module_c_mock)
def test_my_class(mocked_module_a,mocked_module_c):
my_class = Module_B_Class()
my_class.run()
mocked_module_a.my_func.assert_called_once()
mocked_module_c.my_func2.assert_called_once()
注意:为了避免混淆,我将mocked_module_b
重命名为mocked_module_c
。此外,在模块而不是函数上也调用了assert_called_once
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。