如何在 Python 中通过修补来测试函数外部的实例化

问题描述 投票:0回答:1

我有一个大致如下所示的文件:

bar.py

from foo import foo # function that returns an int
from dog import Dog

dog_foo = 4 * foo()
my_dog = Dog(dog_foo)

...

我想测试

my_dog
对象是否已正确实例化为
foo()
乘以 4 的结果。这是一个单元测试,所以我试图避免测试
foo()
的内部结构。事实上,我想打补丁
foo
,这样内部结构就不再重要了。

但是,一旦我将 bar 中的任何内容导入到我的测试中,实例化行就已经运行了。因此,我需要以某种方式导入修补块的内部。我到底应该在这里修补什么?

我尝试了这个,但似乎没有使用补丁:

with mock.patch("foo.foo") as mock_foo:
   mock_foo.return_value = 5
   from bar import my_dog

我也尝试过这个:

with mock.patch("bar.foo") as mock_foo:
   mock_foo.return_value = 5
   from bar import my_dog

这一定是可能的吧?我错过了什么?

python unit-testing import python-unittest.mock
1个回答
0
投票

对于其他发现此问题并且同样陷入困境的人,我想通了!

我正在使用 pytest,并且

bar.py
文件正在测试收集时执行。我有另一个测试文件,正在从
bar.py
导入值。为了收集测试,pytest 正在执行此导入。这意味着
bar.py
在测试收集时执行并且为 sys.modules 所知。因此,它不需要再次执行,只是返回已经计算的值而不是重新执行。

我通过重新加载模块而不是模拟上下文来解决这个问题。测试代码如下所示:

import sys
from importlib import reload
from unittest import mock

def test_my_dog:
    with mock.patch("foo.foo") as mock_foo:
        mock_foo.return_value = 5
        reload(sys.modules.get('bar'))
        from bar import my_dog
    assert mock_foo.call_count == 1
    assert my_dog.dog_foo == 20
    reload(sys.modules.get('bar')) # This resets it for the next run.
© www.soinside.com 2019 - 2024. All rights reserved.