Python测试中如何mock跨模块调用的类及设置不同入参返回值?
问题解决方案
1. Bar作用域无法命中mock的问题
核心原因
你当前的mock值设置方式存在错误,导致真实代码中生成的Parameters实例没有绑定你预设的返回值:
- 你写的
bar_mock().get.return_value中,bar_mock()会生成一个临时的mock实例,你仅给这个临时实例设置了get方法的返回值,真实业务代码中调用Parameters()拿到的是全新的mock实例,自然不存在你设置的返回值,看起来就像mock没有生效。 - 额外排查点:确认
bar.py中导入Parameters的写法和你patch的路径匹配,如果bar.py中是import dir_b.parameters后通过parameters.Parameters使用,你需要patch的路径是path.to.bar.parameters.Parameters而非path.to.bar.Parameters。
修复方案
将mock值的绑定对象改为mock类默认返回的实例,直接使用.return_value代替手动调用()生成临时实例:
@mock.patch("path.to.foo.Parameters") @mock.patch("path.to.bar.Parameters") def test_something(self, bar_mock, foo_mock): # 直接给mock类的默认返回实例设置get方法返回值 foo_mock.return_value.get.return_value = 'val1' bar_mock.return_value.get.return_value = 'val2' Foo().load()
如果要匹配Parameters的Borg单例特性(所有实例共享状态),可以让两个mock类返回同一个mock实例,逻辑更贴近真实实现:
@mock.patch("path.to.foo.Parameters") @mock.patch("path.to.bar.Parameters") def test_something(self, bar_mock, foo_mock): # 全局共用同一个mock参数实例 mock_param = mock.MagicMock() foo_mock.return_value = mock_param bar_mock.return_value = mock_param mock_param.get.return_value = 'val1' Foo().load()
2. 为get方法设置不同入参的返回值
错误原因
你写的bar_mock().get('param.a').return_value是先调用get方法拿到返回的MagicMock对象,再给这个对象设置返回值,完全不会影响get方法本身的返回逻辑。
修复方案
使用side_effect实现参数匹配返回,有两种常用写法:
写法1:自定义匹配函数
def mock_get(param_name): # 按参数映射返回值 params_map = { "param.a": "value_a", "param.b": "value_b" } # 找不到匹配时返回默认值 return params_map.get(param_name, "default_value") mock_param.get.side_effect = mock_get
写法2:使用call对象匹配参数
from unittest.mock import call mock_param.get.side_effect = { call("param.a"): "value_a", call("param.b"): "value_b", }.get
内容的提问来源于stack exchange,提问作者ketla
相关产品推荐
相关产品推荐

