假设一个项目中有两个包:some_package
和another_package
。
# some_package/foo.py:
def bar():
print('hello')
# another_package/function.py
from some_package.foo import bar
def call_bar():
# ... code ...
bar()
# ... code ...
我想测试 another_package.function.call_bar
模拟出 some_package.foo.bar
因为它有一些我想避免的网络 I/O。
这是一个测试:
# tests/test_bar.py
from another_package.function import call_bar
def test_bar(monkeypatch):
monkeypatch.setattr('some_package.foo.bar', lambda: print('patched'))
call_bar()
assert True
令我惊讶的是,它输出的是 hello
而不是 patched
。我试图调试这个东西,在测试中放置一个 IPDB 断点。当我在断点之后手动导入 some_package.foo.bar
并调用 bar()
我得到 patched
。
在我的真实项目中,情况更加有趣。如果我在项目根目录中调用 pytest,我的函数不会被修补,但是当我指定 tests/test_bar.py
作为参数时 - 它可以工作。
据我了解,这与 from some_package.foo import bar
语句有关。如果它在monkeypatching 发生之前执行,则修补失败。但是在上面示例中的压缩测试设置中,补丁在这两种情况下都不起作用。
为什么它在遇到断点后在 IPDB REPL 中起作用?
最佳答案
而 Ronny's answer它会迫使您更改应用程序代码。一般来说,您不应该为了测试而这样做。
相反,您可以显式修补第二个包中的对象。这在 docs for the unittest module 中有所提及.
monkeypatch.setattr('another_package.bar', lambda: print('patched'))
关于python - Pytest monkeypatch 不适用于导入的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31306080/