如何使用mock.patch自动将所有属性设为None而非MagicMock实例?
如何用mock.patch将类属性自动设为None而非MagicMock实例
当使用mock.patch配合spec参数mock类时,类的属性默认会生成MagicMock实例。如果想要让这些属性自动被设为None,可以用以下几种方法实现:
方法一:自动遍历类属性批量设置
通过反射获取原类的所有属性(比如property类型的属性),然后批量将mock类的对应属性设为None:
import mock import inspect class SimpleClass: def __init__(self, a, b) -> None: self._a = a self._b = b @property def a(self): return self._a @a.setter def a(self, value): self._a = value @property def b(self): return self._b @b.setter def b(self, value): self._b = value with mock.patch(f'{__name__}.SimpleClass', spec=SimpleClass) as simple: # 遍历原类的所有property属性 for attr_name, _ in inspect.getmembers(SimpleClass, predicate=lambda x: isinstance(x, property)): setattr(simple, attr_name, None) print(f'a: {simple.a}') print(f'b: {simple.b}')
运行后输出:
a: None b: None
方法二:自定义Mock类实现初始化时自动设值
如果需要复用这个逻辑,可以自定义一个继承自MagicMock的类,在初始化时自动把对应属性设为None:
import mock import inspect class SimpleClass: # 类定义同上 class NoneMagicMock(mock.MagicMock): def __init__(self, spec, *args, **kwargs): super().__init__(spec=spec, *args, **kwargs) # 遍历spec类的property属性并设为None for attr_name, _ in inspect.getmembers(spec, predicate=lambda x: isinstance(x, property)): setattr(self, attr_name, None) with mock.patch(f'{__name__}.SimpleClass', new=NoneMagicMock(spec=SimpleClass)) as simple: print(f'a: {simple.a}') print(f'b: {simple.b}')
方法三:针对实例属性的场景(如果需要mock实例)
如果你的需求是mock类的实例,让实例的属性为None,可以用side_effect来创建实例时自动设置:
import mock class SimpleClass: # 类定义同上 def create_none_instance(*args, **kwargs): # 创建符合spec的实例mock instance = mock.create_autospec(SimpleClass, instance=True) # 设置实例属性为None instance.a = None instance.b = None return instance with mock.patch(f'{__name__}.SimpleClass', side_effect=create_none_instance) as simple: # 创建mock实例 obj = simple() print(f'a: {obj.a}') print(f'b: {obj.b}')
内容的提问来源于stack exchange,提问作者Dan
注:原示例中的
SimpleClass存在递归问题——@property的getter直接返回self.a会触发无限递归,因此上面的代码中修改为用_a/_b作为内部存储变量,这是property的标准写法。
相关产品推荐
相关产品推荐

