为何给MagicMock实例猴子补丁__call__方法未生效?
问题解析:MagicMock调用不触发类
__call__的原因 MagicMock的实例调用逻辑和普通类完全不同,核心原因是它把__call__实现为了实例自身的Mock属性,而非依赖类的__call__方法,具体细节如下:
1. 普通类的实例调用逻辑
对于普通类(比如自定义的Foo),当你调用instance(*args)时,Python的执行路径是:
- 查找
type(instance).__call__(即实例所属类的__call__方法) - 执行该方法完成实例调用逻辑
所以修改实例的__class__、替换类的__call__方法,就能拦截调用行为。
2. MagicMock的特殊设计
Mock/MagicMock的核心设计是动态生成实例级的特殊方法Mock:
- 初始化MagicMock实例时,会自动为
__call__(以及其他特殊方法如__getitem__、__add__等)创建独立的Mock对象,并绑定为实例属性。 - 当你调用MagicMock实例(
mock(*args))时,Python实际执行的是实例自身的__call__属性的调用逻辑,而非类的__call__方法。 - 哪怕你修改了实例的
__class__、替换了类的__call__,但实际调用时优先使用的是实例已有的__call__属性,所以补丁逻辑根本不会被触发。
额外补充:MagicMock通过自定义__getattr__和__setattr__逻辑,确保所有未显式定义的特殊方法都会被动态生成为实例级的Mock——这是它能模拟任意调用、属性的核心,但同时也绕过了类级别的特殊方法查找流程。
内容的提问来源于stack exchange,提问作者tlayton
相关产品推荐
相关产品推荐

