使用unittest.mock.patch装饰器搭配new参数时如何获取被patch对象
报错原因
该报错是unittest.mock.patch的内置设计导致的:当你显式给patch传入new参数时,装饰器模式下不会将替换后的对象注入到测试函数的参数列表中。只有当你不指定new参数、由patch默认生成MagicMock对象作为替换值时,才会自动将生成的Mock对象作为参数注入函数。
而上下文管理器的as语法不受该规则限制,无论你是否传new,都会直接返回替换后的对象,因此你写的test_foo2可以正常运行。
装饰器模式的解决方案
方案1:直接移除多余的函数入参,直接获取替换后的值
你传入的new参数值本身就是替换后的对象,而且patch生效后原目标位置的变量也已经被替换为new的值,你不需要通过参数注入就能拿到:
from unittest.mock import patch class Foo: pass class Bar: pass @patch(__name__ + f".Foo", new=Bar) def test_foo() -> None: # 两种方式都可以拿到等价于上下文管理器中patched_Bar的值 patched_Bar = Bar # 或者直接导入被替换后的Foo,也等于Bar # from __main__ import Foo as patched_Bar _ = 0 # Do stuff
该写法和你给出的test_foo2功能完全等价,也符合你要的简洁装饰器写法要求。
方案2:不传new参数,通过注入的Mock对象自定义替换逻辑
如果你一定要通过函数入参拿到替换后的对象,可以去掉new参数,拿到默认注入的Mock对象后再配置其行为模拟Bar:
@patch(__name__ + f".Foo") def test_foo(patched_Foo) -> None: # 配置Mock的行为和Bar完全一致 patched_Foo.side_effect = Bar # 此时patched_Foo就是你需要的替换对象 _ = 0 # Do stuff
内容的提问来源于stack exchange,提问作者Intrastellar Explorer
相关产品推荐
相关产品推荐

