当使用与pytest fixture集成的mock包中的patch decorator时,我遇到了一些神秘的东西。
我有两个模块
-----test folder
-------func.py
-------test_test.py
def a():
return 1
def b():
return a()
在test_test.py
中 import pytest
from func import a,b
from mock import patch,Mock
@pytest.fixture(scope="module")
def brands():
return 1
mock_b=Mock()
@patch('test_test.b',mock_b)
def test_compute_scores(brands):
a()
补丁装饰似乎与pytest fixture不兼容。有没有人对此有所了解? Tnanks
答案 0 :(得分:11)
将pytest fixture
与mock.patch
一起使用时,测试参数的顺序至关重要。
如果将夹具参数放在模拟的参数之前:
from unittest import mock
@mock.patch('my.module.my.class')
def test_my_code(my_fixture, mocked_class):
然后将模拟对象放在my_fixture
中,并将mocked_class
搜索为固定内容:
fixture 'mocked_class' not found
但是,如果您颠倒顺序,则将Fixture参数放在末尾:
from unittest import mock
@mock.patch('my.module.my.class')
def test_my_code(mocked_class, my_fixture):
那一切都会好起来的。
答案 1 :(得分:4)
从 Python3.3 开始,mock
模块已被拉入unittest
库。还有一个backport(适用于以前版本的Python)作为独立库mock
。
在同一个测试套件中组合这两个库会产生上述错误:
E fixture 'fixture_name' not found
在您的测试套件的虚拟环境中,运行pip uninstall mock
,并确保您没有在核心unittest库旁边使用反向移植的库。卸载后重新运行测试时,如果出现这种情况,您会看到ImportError
。
将此导入的所有实例替换为from unittest.mock import <stuff>
。
答案 2 :(得分:3)
这并没有直接解决您的问题,但有pytest-mock插件允许您改为编写:
def test_compute_scores(brands, mock):
mock_b = mock.patch('test_test.b')
a()
答案 3 :(得分:3)
希望这个旧问题的回答能够帮助别人。
首先,问题不包含错误,因此我们 但我会尝试提供一些帮助我的东西。
如果你想要一个用修补对象装饰的测试,那么为了让它与pytest一起使用你可以这样做:
@mock.patch('mocked.module')
def test_me(*args):
mocked_module = args[0]
或多个补丁:
@mock.patch('mocked.module1')
@mock.patch('mocked.module')
def test_me(*args):
mocked_module1, mocked_module2 = args
pytest正在寻找要在测试函数/方法中查找的灯具的名称。提供*args
参数为查找阶段提供了一个很好的解决方法。因此,要包含具有补丁的夹具,您可以这样做:
# from question
@pytest.fixture(scope="module")
def brands():
return 1
@mock.patch('mocked.module1')
def test_me(brands, *args):
mocked_module1 = args[0]
这对我来说运行python 3.6和pytest 3.0.6。
答案 4 :(得分:2)
我有同样的问题,解决方案对我来说是在1.0.1版本中使用模拟库(之前我在2.6.0版本中使用unittest.mock)。现在它就像一个魅力:)
答案 5 :(得分:1)
如果要应用多个补丁,则注入它们的顺序很重要:
# from question
@pytest.fixture(scope="module")
def brands():
return 1
# notice the order
@patch('my.module.my.class1')
@patch('my.module.my.class2')
def test_list_instance_elb_tg(mocked_class2, mocked_class1, brands):
pass