Python中两种Mock方式的差异与适用场景解析
Python Mock:声明处 vs 使用处的差异、场景与失效原因
核心本质
mock.patch的工作逻辑是替换目标命名空间中的对象引用,而非修改原对象本身。这是理解两种Mock方式差异的核心。
两种Mock方式的差异
作用的命名空间不同
- 声明处Mock(
@mock.patch('my_module.my_function')):替换的是**原模块(my_module)**命名空间里的my_function引用。 - 使用处Mock(
@mock.patch('foo_module.my_function')):替换的是**被测试模块(foo_module)**命名空间里已导入的my_function引用。
- 声明处Mock(
影响范围不同
- 声明处Mock会影响所有直接引用原模块对象的代码;
- 使用处Mock仅影响当前被测试模块内的对象引用,不会干扰其他模块对原对象的调用。
适用场景
声明处Mock适用场景
- 被测试代码直接通过原模块访问对象,比如测试代码里写的是
my_module.my_function(),而非提前导入; - 需要让多个依赖原模块的测试用例共享同一个Mock,或者测试跨模块的调用链时;
- 要Mock的是类、类方法这类需要全局替换的对象时(比如多个模块都用同一个类实例)。
使用处Mock适用场景
- 被测试模块已经通过
from xxx import yyy将对象导入自身命名空间,之后直接调用yyy(); - 只想隔离当前测试用例的Mock,避免影响其他测试或模块的正常逻辑;
- 原模块的对象被多个模块导入,但只需要针对当前被测试模块做Mock时。
为什么声明处Mock有时失效?
举个具体的例子:
假设my_module.py里定义了my_function,foo_module.py执行了from my_module import my_function,然后在自己的函数里直接调用my_function()。
当foo_module导入my_function时,Python会在foo_module的命名空间中创建一个指向原my_function的独立引用。之后你即使替换了my_module里的my_function,foo_module里的那个引用依然指向最初的原函数——因为mock.patch没修改这个引用。
这种情况下,只有替换foo_module命名空间里的那个引用(也就是使用处Mock),才能让被测试代码调用到Mock对象。
内容的提问来源于stack exchange,提问作者Abdel Ysf
相关产品推荐
相关产品推荐

