为何单元测试中unittest patch在跨方法调用时不生效?
问题原因与解决方案
你的猜测完全正确——问题出在同一文件内的函数调用方式。
在storage_utils.py中,foo直接调用bar()时,它引用的是当前文件作用域内的原始bar函数对象,而非你通过patch修改的模块级bar引用。unittest.mock.patch只会修改模块命名空间中的函数,但foo内部的调用并没有指向这个被修改的命名空间,所以mock完全没生效。
解决方案
方案1:修改业务代码(推荐,更符合模块设计规范)
让foo明确调用模块级的bar,确保它指向模块命名空间中的函数:
# src/main/python/storage_utils.py import storage_utils # 导入自身模块 def bar(config_name): return SimpleDataClass(dict(read_config(config_name))) def foo(config_name, path, file_filter, params): bar_info = storage_utils.bar(config_name) # 改为模块级调用 return
修改后你的原有测试代码无需变动,@patch("src.main.python.storage_utils.bar")就能正确替换foo调用的bar。
方案2:不修改业务代码,直接patch目标作用域
如果不想改动业务逻辑,可以直接替换foo所在全局作用域内的bar引用:
from unittest.mock import patch import unittest import storage_utils from your_module import SimpleDataClass # 请替换为实际导入路径 class MyTestCase(unittest.TestCase): @patch.object(storage_utils.foo.__globals__, 'bar') def test_foo_success_path(self, mock_bar): config_name, path, file_filter, params = 'test_config_name', 'test_path', 'test_file_filter', 'test_params' mock_bar.return_value = SimpleDataClass({}) storage_utils.foo(config_name, path, file_filter, params) # 可选:添加断言验证mock是否被正确调用 mock_bar.assert_called_once_with(config_name)
或者也可以简化为字符串路径patch:@patch("storage_utils.bar")(前提是测试文件的导入路径正确),本质和方案1原理一致——都是确保patch的是foo实际引用的那个bar对象。
内容的提问来源于stack exchange,提问作者anthony1234
相关产品推荐
相关产品推荐

