Python unittest.mock:为何定义层打补丁无效?求深层解析
为什么patch
a.SomeClass对b.some_function无效? 要搞懂这个问题,得先明白Python的导入逻辑和引用机制:
1. 导入时的引用复制
先看你的项目代码:
a.py定义SomeClass:
class SomeClass: pass
b.py通过from a import SomeClass导入,并在函数里使用:
from a import SomeClass def some_function(): return SomeClass()
当b模块第一次被加载时,from a import SomeClass会做两件事:
- 找到
a模块命名空间里的SomeClass类对象 - 在
b模块自己的命名空间里,创建一个名为SomeClass的变量,直接指向这个真实的类对象
这时候,a.SomeClass和b.SomeClass是同一个对象的两个独立引用——就像两个人各拿了一张指向同一栋房子的纸条,纸条本身是分开的,但指向的是同一个地方。
2. patch的作用范围
patch('a.SomeClass')的本质是:修改a模块命名空间里的SomeClass变量,让它指向一个mock对象,而不再是原来的真实类。
但问题在于,b模块里的SomeClass变量是早就复制好的引用,它不会自动跟着a模块里的变化更新。就像你把自己纸条上的地址改成了假房子,但你朋友手里的纸条还是原来的真实地址,他去找的时候还是会去真房子,不会去你改的假房子。
所以当some_function调用SomeClass()时,它用的是b模块自己命名空间里的那个真实类引用,完全没用到被patch过的a.SomeClass。
3. 正确的patch方式
要让mock生效,你需要patch的是b模块里的SomeClass引用,也就是用:
patch('b.SomeClass')
这样替换的是b模块命名空间里的SomeClass变量,当some_function调用SomeClass()时,就会使用这个mock对象了。
内容的提问来源于stack exchange,提问作者user1187968
相关产品推荐
相关产品推荐

