pytest-mock验证类方法assert_called_with失败问题求助
作为刚上手pytest和mock的新手,碰到assert_called_with失败确实很头疼。我先结合你给出的目标代码,拆解一下常见的坑和解决办法。
首先明确你的目标代码逻辑:Main类的test_func会调用自身的internal_func(20),然后返回计算结果。你的测试应该是想验证internal_func是否确实被传入20调用了对吧?
先把你给出的代码贴出来方便参考:
目标代码(src/main.py)
class Main(object): def __init__(self, my_var=None): self.var = my_var def internal_func(self, var=10): my_var = var + 20 return my_var def test_func(self): val = self.internal_func(20) return val + 40
常见错误原因及修正方案
1. 错误导入/使用mocker fixture
你在测试代码里写了from pytest_mock import mocker,这是错的!pytest-mock的mocker是一个fixture,不需要导入,而是要作为测试函数的参数传入,pytest会自动帮你初始化它。
2. Mock对象选错了(实例方法vs类方法)
新手最容易踩的坑:如果Mock的是类的方法,而不是实例的方法,断言时会因为多了self参数失败。比如:
# 错误示例:Mock类方法 def test_test_func(mocker): # Mock的是Main类的internal_func mock_internal = mocker.patch('src.main.Main.internal_func') mock_internal.return_value = 40 main_instance = Main() main_instance.test_func() # 这里会失败!因为实际调用是 internal_func(self, 20),参数是(main_instance, 20) mock_internal.assert_called_with(20)
正确的做法是Mock实例的方法,这样就不会带上self参数的干扰:
# 正确示例:Mock实例方法 def test_test_func(mocker): # 先创建实例 main_instance = Main() # 针对这个实例,Mock它的internal_func方法 mock_internal = mocker.patch.object(main_instance, 'internal_func') # 给Mock设置返回值,让test_func能正常走完逻辑 mock_internal.return_value = 40 # 对应原方法internal_func(20)的返回值40 # 调用要测试的方法 result = main_instance.test_func() # 验证调用参数:和test_func里的调用完全匹配(位置参数20) mock_internal.assert_called_with(20) # 可选:验证最终返回值是否符合预期 assert result == 80
3. 参数匹配形式不统一
assert_called_with对参数的形式(位置参数/关键字参数)要求严格。比如如果你的测试代码里写的是mock_internal.assert_called_with(var=20),但实际test_func里是用位置参数self.internal_func(20)调用的,这时候断言就会失败。
如果想忽略参数形式,或者不确定参数是位置还是关键字,可以用mocker.ANY来匹配,比如:
mock_internal.assert_called_with(mocker.ANY) # 只要被调用就行,不管参数 # 或者只匹配参数值,不管是位置还是关键字 mock_internal.assert_called_once_with(20)
4. 排查小技巧:打印实际调用参数
如果还是搞不清为什么断言失败,可以在断言前打印mock_internal.call_args,看看实际调用时传了什么参数:
print(mock_internal.call_args) # 比如会输出:call(20) 或者 call(<__main__.Main object at 0x...>, 20)
这样就能直观对比预期参数和实际参数的差异,快速定位问题。
内容的提问来源于stack exchange,提问作者suri

