Unittest.mock.patch无法替换装饰器,测试add函数失败求助
解决Unittest.mock.patch替换装饰器失效的问题
你的patch失败核心原因是模块加载阶段装饰器已执行完毕:当add.py被首次导入时,@decor语法会立刻调用原decor函数包装add,生成被装饰后的版本并存在模块命名空间中。后续patchadd.decor仅替换了模块内的decor函数,但已经生成的add函数不会重新被装饰。
以下是两种可行的修复方案:
方案一:Patch后重新加载模块
利用importlib.reload在patch生效后重新加载add模块,让模块内的@decor使用mock后的装饰器重新包装add函数。
修改后的test_script.py代码:
import functools from unittest.mock import patch import importlib import add # 先导入模块,供后续reload使用 def mock_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) # 直接返回原函数结果,不额外加1 return wrapper def test_add(): with patch('add.decor', new=mock_decorator): importlib.reload(add) # 重新加载模块,触发mock装饰器生效 result = add.add(1, 1) assert result == 2
方案二:直接调用原函数的__wrapped__属性
由于你使用了functools.wraps,它会将原函数保存到被装饰函数的__wrapped__属性中,可以直接绕过装饰器调用原函数:
修改后的test_script.py代码:
from add import add def test_add(): result = add.__wrapped__(1, 1) # 调用未被装饰的原始add函数 assert result == 2
这个方法更简洁,但依赖functools.wraps的实现(如果装饰器未使用该工具,可能不存在__wrapped__属性)。
内容的提问来源于stack exchange,提问作者Swalt
相关产品推荐
相关产品推荐

