You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单元测试中验证导入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()

问题原因解析

  1. 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后的函数。

  2. 模块缓存问题:
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 07:06:21