mock.patch 在 pytest 夹具中不起作用?

ca9*_*3d9 2 python pytest

f2()我需要在下面编写测试用例mod1

mod1.py

from mod_x import X

def f1():
    raise Exception('Test shouldn''t call real f1()')

def f2():
    f1()
Run Code Online (Sandbox Code Playgroud)

以下是导入的mod_x.

mod_x.py

class Y:
    def func2(self):
        raise Exception("Shouldn't be called")

class X:
    def __init__(self):
        self.producer = Y()
Run Code Online (Sandbox Code Playgroud)

这是测试代码test_mod1.py。它应该修补,所以不应该调用mod1.f1真实的。f1()

import mod1
import pytest
from unittest import mock

@pytest.fixture()
@mock.patch('mod1.f1')
def patched_mocked(mocked_function):
    x_mock = mock.Mock(mod1.X)
    x_mock.producer = mock.Mock()
    x_mock.producer.func2 = lambda : None
    mocked_function.return_value = x_mock
    return x_mock   

def test_1(patched_mocked):
    mod1.f2() # f2() shouldn't call the real f1() because of patching
    # assert ....

def test_2(patched_mocked):
    mod1.f2()
    # assert ....
Run Code Online (Sandbox Code Playgroud)

然而,

test_mod1.py FF [100%]

=================================================== =================================================== ==== 失败 =============================================== =================================================== =========
_________________________________________________________________________________________________________ 测试_1 _____________________________________________________________________________________________________

patched_mocked_function =

    def test_1(patched_mocked_function):
> mod1.f2()

test_mod1.py:15:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
mod1.py:7: 在 f2 中
    f1()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    def f1():
> raise Exception('测试不应调用真正的 f1()')
E 例外:测试不应调用真正的 f1()

mod1.py:4:异常

MrB*_*men 7

您不能在固定装置上使用补丁装饰器,因为模拟将在您返回固定装置时恢复。您需要确保仅在测试结束后(例如在夹具生命周期之后)才恢复模拟(例如超出范围):

@pytest.fixture()
def patched_mocked():
    with mock.patch('mod1.f1') as mocked_function:
        x_mock = mock.Mock(mod1.X)
        x_mock.producer = mock.Mock()
        x_mock.producer.func2 = lambda: None
        mocked_function.return_value = x_mock
        yield x_mock
Run Code Online (Sandbox Code Playgroud)

yield在这种情况下,只有在返回后(即测试完成后)才会恢复模拟。