Python中如何对Mock对象排序?解决MagicMock排序报错问题
解决Mock对象排序报错的方法
问题原因
MagicMock会动态拦截__lt__这类特殊方法的调用,即便你继承重写了该方法,默认也不会触发自定义逻辑,导致排序时依然报错。
方案1:用普通自定义类替代MagicMock(推荐)
如果仅需模拟path的比较逻辑,无需依赖MagicMock,直接实现极简模拟类即可,借助functools.total_ordering装饰器自动生成全量比较方法:
from functools import total_ordering import random from typing import Optional @total_ordering class MockPath: def __init__(self, name: Optional[str] = None): self.name = name or str(random.randint(1, 10000)) def __lt__(self, other) -> bool: # 排序结果不重要的话,也可以用`id(self) < id(other)`替代基于name的比较 return self.name < other.name def __eq__(self, other) -> bool: return self.name == other.name
使用时直接给对象的path属性赋值该类实例:
obj1.path = MockPath("file1") obj2.path = MockPath("file2")
方案2:给MagicMock实例手动绑定__lt__方法
如果必须使用MagicMock,直接给实例添加__lt__方法,绕过MagicMock的特殊方法拦截:
from unittest.mock import MagicMock import random path_mock1 = MagicMock() path_mock1.name = str(random.randint(1, 10000)) path_mock1.__lt__ = lambda self, other: self.name < other.name path_mock2 = MagicMock() path_mock2.name = str(random.randint(1, 10000)) path_mock2.__lt__ = lambda self, other: self.name < other.name obj1.path = path_mock1 obj2.path = path_mock2
方案3:修改自定义MockPath类,避免方法被覆盖
若坚持继承MagicMock,需在初始化时将自定义__lt__绑定为实例属性,防止被MagicMock的动态逻辑覆盖:
from unittest.mock import MagicMock import random from typing import Optional class MockPath(MagicMock): def __init__(self, name: Optional[str] = None, *args, **kw): super().__init__(*args, **kw) self.name = name or str(random.randint(1, 10000)) # 手动绑定自定义比较方法 self.__lt__ = self._compare_lt def _compare_lt(self, other) -> bool: return self.name < other.name
实例化MockPath后,__lt__方法就能正常触发自定义逻辑,排序时不再报错。
内容的提问来源于stack exchange,提问作者Jacob Pavlock
相关产品推荐
相关产品推荐

