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

为何单元测试中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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:22:17