Pytest Monkeypatch对已导入的函数不生效问题咨询
问题根因
补丁未生效的核心原因是补丁路径和实际运行时加载的模块路径不匹配,其次可能是导入顺序优先级问题:
- 你在补丁中指定的路径是
app.bar.generate,但测试代码里直接使用from bar import coo导入,说明运行测试时的Python路径中,bar是顶层模块,而非app包的子模块。此时你实际打的补丁是不存在的命名空间下的属性,并没有作用到测试代码实际引用的bar.generate属性上,自然不会触发mock逻辑。 - 若你的包结构确实是将
bar.py放在app子包下,那测试模块的顶层导入from bar import coo本身就会提前将bar作为顶层模块加载,早于conftest中fixture的执行时机,fixture后续给app.bar.generate打的补丁无法作用到已经加载完成的bar模块上。
解决方案
按照优先级可以选择以下任意一种方案:
- 修正补丁路径与实际导入路径对齐
直接匹配测试代码中导入的模块路径,修改conftest中的补丁逻辑:
# conftest.py 修改后 monkeypatch.setattr("bar.generate", mock_generate)
如果你的测试代码实际使用的是包导入from app.bar import coo,再保留app.bar.generate的补丁路径即可。
- 延迟测试模块的导入时机
把测试模块中的导入动作放到测试函数内部,保证导入发生在fixture补丁执行之后:
# test_bar.py 修改后 def test_coo(): from bar import coo coo()
- 直接Patch原始定义的函数(备选)
如果确认没有其他模块提前导入绑定该函数,也可以直接patch foo模块中定义的原始函数:
# conftest.py 修改后 monkeypatch.setattr("foo.generate_things_based_on_other_things", mock_generate)
内容的提问来源于stack exchange,提问作者Ronny Efronny
相关产品推荐
相关产品推荐

