pytest 模拟导入包中的函数时失败

0 投票
1 回答
20 浏览
提问于 2025-04-12 01:08

pytest-mock 已经正确安装:

> pip list | grep pytest
pytest                7.4.2
pytest-mock           3.14.0

这个单元测试成功通过了:

import pytest

class A:
    def __init__(self, value):
        self.value = value

def get_a() -> A:
    return A(1)

@pytest.fixture
def mocked_A(mocker):
    a = A(2)
    mocker.patch(f"{__name__}.get_a", return_value=a)

def test_mocked_a(mocked_A) -> None:
    a = get_a()
    assert a.value == 2

现在,如果我把 A 和 get_A 移到 mypackage.mymodule 里,模拟就不再有效了。

import pytest

# note: these imports work: mypackage is correctly installed
from mypackage.mymodule import A, get_a

@pytest.fixture
def mocked_A(mocker):
    a = A(2)
    mocker.patch("mypackage.mymodule.get_a", return_value=a)

def test_mocked_a(mocked_A) -> None:
    a = get_a()
    assert a.value == 2

测试失败,出现了这个错误:

mocked_A = None

    def test_mocked_a(mocked_A) -> None:
        a = get_a()
>       assert a.value == 2
E       assert 1 == 2
E        +  where 1 = <mypackage.mymodule.A object at 0x7f063e3f2c80>.value

test_a.py:13: AssertionError
=============================================================================== short test summary info ================================================================================
FAILED test_a.py::test_mocked_a - assert 1 == 2

看起来 get_a 没有被模拟。请问我做错了什么吗?

1 个回答

1

和导入的模块或包不同,get_a只是一个普通的标识符,它指向你想要修改的函数,而不需要在mypackage.mymodule中查找,因为这个查找在导入时已经完成了。所以在这种情况下,你需要直接通过f"{__name__}.get_a"来修改,就像你第一次测试时那样。这并不是pytest-mock的特殊行为。

撰写回答