Python Unittest如何Mock被__init__.py导入的外部函数?
解决Mock失效问题的两种方案
问题原因
你的Mock失效是因为__init__.py里导入my_func2时,my_package.my_func2模块会被提前加载。此时my_func2.py里用from my_package.my_func1 import my_func1导入的函数,会以变量形式存在于my_func2模块的命名空间中,这个变量已经绑定了原始的my_func1。后续测试中的patch如果没命中这个提前绑定的变量,就会失效。
方案一:修改业务代码的导入方式(推荐)
把my_func2.py里的直接导入改为模块级导入,这样每次调用my_func2时都会动态去原模块查找my_func1,不受提前加载的影响。
修改后的my_func2.py:
import my_package.my_func1 def my_func2(): return my_package.my_func1.my_func1()
对应的测试代码只需要patch原始函数的路径即可:
import unittest from unittest.mock import patch from my_package.my_func2 import my_func2 class TestMyFunc2(unittest.TestCase): @patch("my_package.my_func1.my_func1") def test_my_func2(self, mock_my_func1): mock_my_func1.return_value = "MOCK DONE" result = my_func2() print(result) self.assertEqual(result, "MOCK DONE") if __name__ == "__main__": unittest.main()
方案二:在测试中清除模块缓存(无需修改业务代码)
如果不能改业务代码,可以在测试方法里先删除已加载的模块缓存,重新导入my_func2,确保patch能替换到模块里的my_func1变量。
修改后的测试代码:
import unittest import sys from unittest.mock import patch class TestMyFunc2(unittest.TestCase): @patch("my_package.my_func2.my_func1") def test_my_func2(self, mock_my_func1): # 清除my_package相关的模块缓存 for module in list(sys.modules.keys()): if module.startswith("my_package"): del sys.modules[module] # 重新导入my_func2 from my_package.my_func2 import my_func2 mock_my_func1.return_value = "MOCK DONE" result = my_func2() print(result) self.assertEqual(result, "MOCK DONE") if __name__ == "__main__": unittest.main()
内容的提问来源于stack exchange,提问作者sceptre
相关产品推荐
相关产品推荐

