如何使用unittest.mock的assert_called_once_with校验传参实例属性正确性
你看到的错误输出里的内存地址只是对象repr的打印内容,unittest.mock的参数对比本质是用==运算符判断的,不是直接对比repr,报错的核心原因是你重写的__eq__方法没有正确返回True。
方案1:修复__eq__实现
你的__eq__方法没有做类型校验,当对比的对象不是对应类的实例时,访问other.id会抛出AttributeError,Python遇到运算符方法抛出异常时会默认返回False,导致对比失败。你可以优化__eq__的实现:
def __eq__(self, other): # 先判断对比对象是否为同类实例,避免属性访问报错 if not isinstance(other, self.__class__): return False return ( self.id == other.id and self.users == other.users )
方案2:手动提取参数校验(更可控)
如果不想修改原业务类的逻辑,可以不用依赖assert_called_once_with的自动对比,手动提取参数逐个校验属性,报错时还能直接定位到不匹配的字段:
# 先校验调用次数是否符合预期 mock_add_user.assert_called_once() # 提取实际调用时传入的位置参数 actual_context, actual_user1, actual_user2, actual_users = mock_add_user.call_args.args # 逐个校验属性 assert actual_context == context_fix assert actual_user1.id == expected_user_obj1.id assert actual_user1.users == expected_user_obj1.users assert actual_user2.id == expected_user_obj2.id assert actual_user2.users == expected_user_obj2.users assert actual_users == users
方案3:自定义通用匹配器(适合复用场景)
如果需要在多处用到属性对比逻辑,可以写一个通用匹配器适配assert_called_once_with的调用规则:
class AttrMatcher: def __init__(self, expected, check_attrs): self.expected = expected self.check_attrs = check_attrs def __eq__(self, other): for attr in self.check_attrs: if getattr(self.expected, attr) != getattr(other, attr): return False return True # 调用断言时直接传入匹配器即可 mock_add_user.assert_called_once_with( context_fix, AttrMatcher(expected_user_obj1, ["id", "users"]), AttrMatcher(expected_user_obj2, ["id", "users"]), users )
内容的提问来源于stack exchange,提问作者Wincenty Bertoni Lech
相关产品推荐
相关产品推荐

