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

Python如何正确mock用于初始化类变量的函数,解决导入提前执行问题?

问题原因

你的猜测完全正确:类变量的赋值逻辑会在所属模块第一次被导入时就执行。你当前的测试代码在文件顶部就导入了ClassToTest,执行导入的节点some_func还没有被mock,ClassToTest.var已经被赋值为原函数的返回结果,后续再打补丁自然不会生效。

解决方案

方案1:补丁生效后再导入被测类

不要在测试文件顶部导入ClassToTest,将导入逻辑移到补丁已经生效的测试方法内部:

# test_code.py
import unittest
from unittest import mock

def mock_function():
    return {"someOtherKey": "someOtherValue"}

class Test_Code(unittest.TestCase):
    @mock.patch('src.code.some_func', new=mock_function)
    def test_ClassToTest(self):
        # 补丁生效后再导入类,此时类变量初始化会调用mock后的函数
        from src.code import ClassToTest
        self.assertEqual(ClassToTest.var, {"someOtherKey": "someOtherValue"})

方案2:重新加载模块触发类变量重新初始化

如果已经提前导入了模块,可以用importlib.reload在补丁生效后重新加载模块,类定义会重新执行,类变量也会重新赋值:

# test_code.py
import unittest
from unittest import mock
import importlib
# 仅导入模块,不提前初始化类
from src import code

def mock_function():
    return {"someOtherKey": "someOtherValue"}

class Test_Code(unittest.TestCase):
    @mock.patch('src.code.some_func', new=mock_function)
    def test_ClassToTest(self):
        # 重新加载模块,触发类变量重新初始化
        importlib.reload(code)
        self.assertEqual(code.ClassToTest.var, {"someOtherKey": "someOtherValue"})

注意:如果多个测试用例依赖该模块,重新加载可能会影响其他测试的上下文,建议测试执行完成后再次重载恢复原始状态,或者限定补丁的作用范围。

方案3:业务代码优化为懒加载(推荐)

如果允许调整业务代码,可以将类变量改为懒加载形式,避免模块导入阶段就执行带外部依赖的逻辑,后续mock也不需要调整导入顺序:

# code.py 调整后
def some_func():
    # doing some connections and stuff
    return {'someKey': 'someVal'}

class ClassToTest:
    _var = None
    
    @classmethod
    @property
    def var(cls):
        if cls._var is None:
            cls._var = some_func()
        return cls._var

调整后你原本的测试代码不需要修改导入逻辑也可以正常mock生效。


内容的提问来源于stack exchange,提问作者Vivek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:27:03