@Patch装饰器与pytest fixture不兼容

时间:2014-07-31 11:08:03

标签: python mocking pytest

当使用与pytest fixture集成的mock包中的patch decorator时,我遇到了一些神秘的东西。

我有两个模块

    -----test folder
          -------func.py
          -------test_test.py
在func.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

6 个答案:

答案 0 :(得分:11)

将pytest fixturemock.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