使用from语句导入函数时如何在unittest中正确patch该函数?
Python单元测试from导入场景patch失效问题解答
失效原因
Python的导入机制决定了引用绑定的位置:
- 当业务代码使用
from module1 import function1导入时,会将function1的引用直接绑定到业务模块自身的命名空间中,相当于业务模块里有一个独立的变量指向原module1.function1对象。 - 你测试代码中patch的路径是
module1.function1,仅修改了module1命名空间下的引用,不会影响业务模块已经提前复制好的独立引用,因此业务代码调用的还是原始函数。 - 当你把业务代码导入改成
import module1,调用时写module1.function1(),每次执行都会去module1的命名空间查找引用,此时patchmodule1.function1就会生效。
正确处理方案
你可以根据业务场景二选一:
- 方案1:不修改业务代码的导入逻辑,调整patch的目标路径,直接patch业务模块命名空间下的
function1。假设你的业务代码存放在business_module.py中,测试代码修改如下:
from unittest import patch from business_module import function2 def test_function2(): func1_value = 5 # 注意此处patch路径为业务模块的function1,而非原模块的 with patch("business_module.function1", return_value=func1_value) as patched_func1: function2_value = function2() assert function2_value == 2*func1_value
- 方案2:保持测试代码的patch路径不变,调整业务代码的导入和调用方式,改为每次从原模块查找:
业务代码修改为:
import module1 def function2(): function1_result = module1.function1() return 2*function1_result
核心原则:patch的目标永远是代码实际调用的位置的引用,而非函数定义位置的引用。
内容的提问来源于stack exchange,提问作者Daniel Wyatt
相关产品推荐
相关产品推荐

