使用Python Mock Patch测试类未生效,求排查问题原因
问题分析与解决方案
你遇到的是mock/patch中非常典型的路径引用陷阱,核心原因是没搞清楚patch的作用对象:patch替换的是代码实际使用的那个对象引用,而非你随便指定的某个路径。
为什么你的代码没生效?
当你在test.py里执行from lib.inventory import Inventory时,相当于把lib.inventory模块里的Inventory类复制了一份到test模块的命名空间里。而你用@patch('lib.inventory.Inventory')替换的只是lib.inventory模块里的那个Inventory引用,但test模块里的Inventory还是指向原来的类,所以打印时会出现原类和Mock对象分离的情况。
两种可行的修复方案
方案1:patch测试模块里的Inventory引用
既然你的测试代码直接使用的是test模块里的Inventory,那直接patch这个位置即可:
import unittest from mock import patch import time from lib.inventory import Inventory class MyTest(unittest.TestCase): # 把patch目标改成test模块里的Inventory @patch('test.Inventory') def test_retrieve_project_id(self,mock_inventory): print("####################") print(Inventory) # 现在会输出MagicMock对象 print(mock_inventory) print("####################")
方案2:通过模块引用使用Inventory
修改测试代码的导入方式,直接引用lib.inventory模块里的Inventory,这样patchlib.inventory.Inventory就会生效:
import unittest from mock import patch import time from lib import inventory # 导入整个模块 class MyTest(unittest.TestCase): @patch('lib.inventory.Inventory') def test_retrieve_project_id(self,mock_inventory): print("####################") print(inventory.Inventory) # 使用模块内的引用,会被patch替换 print(mock_inventory) print("####################")
关键概念总结
记住mock/patch的核心原则:patch where the object is used, not where it's defined(patch对象被使用的位置,而非被定义的位置)。如果你的代码(测试或被测试逻辑)是通过from X import Y导入的,那Y的引用在当前模块里,这时候要patch当前模块的Y;如果是通过import X然后用X.Y,那patchX.Y就可以。
内容的提问来源于stack exchange,提问作者dominique poisson
相关产品推荐
相关产品推荐

