python - Pytest monkeypatch 不适用于导入的函数

标签 python unit-testing pytest

假设一个项目中有两个包:some_packageanother_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/

相关文章:

javascript - Stryker 和 Jest 的麻烦

javascript - 如何在 Angular js 测试中指定 http 响应顺序?

python - 无法将元组用作字典键?

Python/Django |如何存储已发送的电子邮件?

unit-testing - Glimmer 中的组件单元测试

python - pytest 'No module named ...' 用于在测试模块中导入

python - pytest-将 fixture 传递给mark.parametrize

python-2.7 - 在pytest框架中的另一个测试用例中调用测试用例

python - 使用可变数量的上下文管理器替代 contextlib.nested

python - 如何在gae上建立聊天室,是否有音频python框架来做到这一点?