如何在Python中创建可相加的Mock对象以测试代码?
解决Mock对象加法及调用验证问题
这里有两种可靠的方法来解决你的问题,既可以让Mock支持加法操作,又能精确验证整个调用链是否符合预期:
方案一:为特定Mock属性定制加法行为(推荐用于单一场景)
这种方法直接针对m.a的加法行为做定制,能精准捕获加法结果并验证后续的c()调用:
import unittest import unittest.mock def to_be_tested(x): return round((x.a + x.b).c()) class Test_X(unittest.TestCase): def test_x(self): m = unittest.mock.Mock() # 创建一个Mock作为加法运算的返回结果,它会被用来调用.c() sum_mock = unittest.mock.Mock() # 给m.a的__add__方法设置返回值为sum_mock m.a.__add__ = unittest.mock.Mock(return_value=sum_mock) # 执行被测函数 to_be_tested(m) # 验证m.a的加法方法被正确调用,参数是m.b m.a.__add__.assert_called_once_with(m.b) # 验证sum_mock的c()方法被调用 sum_mock.c.assert_called_once() # 额外:如果需要验证round的结果,可以给sum_mock.c()设置返回值 sum_mock.c.return_value = 3.7 result = to_be_tested(m) self.assertEqual(result, 4)
方案二:创建支持加法的通用Mock子类(适合多场景复用)
如果你的测试中需要大量支持加法的Mock,可以自定义一个Mock子类,让所有实例默认支持加法:
import unittest import unittest.mock def to_be_tested(x): return round((x.a + x.b).c()) class AddableMock(unittest.mock.Mock): def __add__(self, other): # 加法返回另一个AddableMock实例,确保后续能调用.c() return AddableMock() class Test_X(unittest.TestCase): def test_x(self): m = AddableMock() # 执行被测函数 to_be_tested(m) # 验证m.a和m.b被访问过 self.assertIn(('a',), m.mock_calls) self.assertIn(('b',), m.mock_calls) # 如果需要验证加法后的c()调用,可以进一步跟踪: class TrackedAddableMock(AddableMock): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_result = None def __add__(self, other): self.add_result = TrackedAddableMock() return self.add_result m = TrackedAddableMock() to_be_tested(m) # 验证加法结果的c()方法被调用 m.a.add_result.c.assert_called_once()
为什么你之前的尝试失败?
你之前设置m.a.__add__ = lambda a, b: unittest.mock.Mock(a, b)时,错误地把a和b作为Mock的spec参数传入了,这不是你想要的——你应该直接创建一个无参数的Mock实例:lambda a, b: unittest.mock.Mock()。另外,AttributeError大概率是因为这个参数错误导致Mock初始化异常,进而没有生成预期的c属性。
总结
- 如果你只需要验证单一的调用链,方案一更直接,能精确控制每个Mock的行为并验证;
- 如果你有多个需要支持加法的Mock场景,方案二的自定义子类能减少重复代码。
内容的提问来源于stack exchange,提问作者Alfe
相关产品推荐
相关产品推荐

