在pytest monkeypatch中Mock函数遇AttributeError,__name__应替换为?
解决Monkeypatch Mock函数时的AttributeError问题
问题根源
你当前代码中用__name__(模块名字符串)作为monkeypatch.setattr的第一个参数,可能因为模块命名空间加载问题,或者直接调用本地函数而非模块属性,导致出现AttributeError或mock不生效。
可行解决方案
方案一:使用当前模块对象(适用于函数和测试在同一文件)
导入sys模块获取当前模块对象,同时调用模块的函数属性而非本地引用:
import sys def my_function(): return "original" def mock_my_function(): return "mocked" def test_my_function(monkeypatch): # 用模块对象替代模块名字符串 monkeypatch.setattr(sys.modules[__name__], 'my_function', mock_my_function) # 调用模块的my_function属性,确保使用被mock后的版本 assert sys.modules[__name__].my_function() == "mocked"
方案二:拆分被测试函数到独立模块(更规范的测试结构)
将my_function放到单独的模块文件(如my_module.py):
my_module.py
def my_function(): return "original"
测试文件中导入该模块,直接patch模块对象:
from my_module import my_function def mock_my_function(): return "mocked" def test_my_function(monkeypatch): # 直接传入模块对象或模块名字符串 monkeypatch.setattr("my_module", 'my_function', mock_my_function) # 调用导入的函数,此时已被mock assert my_function() == "mocked"
为什么原代码出错
如果my_function是模块级定义的,理论上__name__可行,但报错通常是因为:
- 函数并非模块级定义(比如写在测试函数内部),模块中无该属性
- pytest运行环境的模块加载机制,导致通过模块名字符串无法定位到目标函数
用模块对象替代字符串,能精准定位要修改的属性,避免此类问题。
内容的提问来源于stack exchange,提问作者vmp
相关产品推荐
相关产品推荐

