如何在单元测试中验证导入Python脚本时函数是否被调用
解决导入模块时函数调用的单元测试问题
你的问题出在两个核心点:patch的目标位置错误,以及模块导入缓存导致代码未重新执行,下面是修正后的测试方案和原因解析:
正确的测试代码
import sys from unittest import mock import unittest class TestFooImport(unittest.TestCase): @mock.patch("bar.some_func") def test_func_called_on_import(self, some_func_mock): # 清除已缓存的foo模块,确保每次测试都重新执行导入逻辑 if 'foo' in sys.modules: del sys.modules['foo'] import foo some_func_mock.assert_called_once() if __name__ == '__main__': unittest.main()
问题原因解析
Patch目标错误:
你的foo.py里用了from bar import some_func,这相当于把bar.some_func直接复制到foo的命名空间中。你之前patch的是foo.some_func,但这个替换操作是在foo导入之后才生效的——而some_func()在导入foo的瞬间就已经执行了,mock根本没来得及替换它。正确的做法是patch原始来源bar.some_func,这样foo在导入时拿到的就是mock后的函数。模块缓存问题:
Python会把已经导入过的模块存在sys.modules字典里,第二次import foo时会直接读取缓存,不会重新执行模块顶层的代码。所以每次测试前必须删除sys.modules里的foo,确保模块被重新加载,some_func()会再次执行。
另一种可选方案(直接控制导入时机)
如果需要更灵活地控制mock和导入的顺序,也可以用上下文管理器的方式实现:
import sys from unittest import mock import unittest class TestFooImport(unittest.TestCase): def test_func_called_on_import(self): if 'foo' in sys.modules: del sys.modules['foo'] # 先启动mock,再导入foo with mock.patch("bar.some_func") as some_func_mock: import foo some_func_mock.assert_called_once()
内容的提问来源于stack exchange,提问作者Jeroen
相关产品推荐
相关产品推荐

