@Patch装饰器与pytest fixture不兼容

Hel*_*lad 25 python mocking pytest

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

我有两个模块

    -----test folder
          -------func.py
          -------test_test.py
Run Code Online (Sandbox Code Playgroud)

在func.py中:

    def a():
        return 1

    def b():
        return a()     
Run Code Online (Sandbox Code Playgroud)

在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()
Run Code Online (Sandbox Code Playgroud)

似乎补丁装饰与pytest fixture不兼容.有没有人对此有所了解?Tnanks

bux*_*bux 32

使用pytest fixturemock.patch,测试参数顺序至关重要.

如果在模拟的参数之前放置fixture参数:

from unittest import mock

@mock.patch('my.module.my.class')
def test_my_code(my_fixture, mocked_class):
Run Code Online (Sandbox Code Playgroud)

然后模拟对象将进入my_fixture并将mocked_class作为一个夹具搜索:

fixture 'mocked_class' not found
Run Code Online (Sandbox Code Playgroud)

但是,如果您颠倒顺序,将fixture参数放在最后:

from unittest import mock

@mock.patch('my.module.my.class')
def test_my_code(mocked_class, my_fixture):
Run Code Online (Sandbox Code Playgroud)

那一切都会好的.

  • 这是解决方案,而不是康拉德的解决方案。 (2认同)

404*_*404 7

希望这个老问题的答案会对某人有所帮助。

首先,问题不包括错误,所以我们真的不知道发生了什么。但我会尽力提供一些对我有帮助的东西。

如果你想要一个用修补对象装饰的测试,那么为了让它与 pytest 一起工作,你可以这样做:

@mock.patch('mocked.module')
def test_me(*args):
    mocked_module = args[0]
Run Code Online (Sandbox Code Playgroud)

或者对于多个补丁:

@mock.patch('mocked.module1')
@mock.patch('mocked.module')
def test_me(*args):
    mocked_module1, mocked_module2 = args
Run Code Online (Sandbox Code Playgroud)

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]
Run Code Online (Sandbox Code Playgroud)

这对我运行 python 3.6 和 pytest 3.0.6 有用。


The*_*inn 5

Python3.3开始,该mock模块已被拉unittest入库中。还有一个反向端口(用于Python的早期版本)可以作为独立库使用mock

将这两个库组合到同一测试套件中会产生上述错误:

E       fixture 'fixture_name' not found
Run Code Online (Sandbox Code Playgroud)

在测试套件的虚拟环境中,运行pip uninstall mock,并确保没有在核心unittest库旁边使用反向移植库。卸载后重新运行测试时,会看到ImportErrors。

将此导入的所有实例替换为from unittest.mock import <stuff>


cod*_*ior 5

如果您要应用多个补丁,则注入它们的顺序很重要:

# 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
Run Code Online (Sandbox Code Playgroud)


小智 -7

我遇到了同样的问题,解决方案是在 1.0.1 版本中使用模拟库(在我在 2.6.0 版本中使用 unittest.mock 之前)。现在它就像一个魅力:)