首页 > 解决方案 > mock.patch 在 pytest 夹具中不起作用?

问题描述

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

mod1.py

from mod_x import X

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

def f2():
    f1()

以下是导入的mod_x.

mod_x.py

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

class X:
    def __init__(self):
        self.producer = Y()

这是测试代码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 ....

然而,

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()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

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

mod1.py:4:异常

标签: pythonpytest

解决方案


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

@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

在这种情况下,模拟仅在返回后yield恢复,即测试完成后。


推荐阅读