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

Python unittest的setUp函数未应用类级别声明的patch mock问题

问题原因

你遇到的问题是unittest框架的执行顺序和patch装饰器的生效时机不匹配导致的:
类级别挂载的@patch装饰器,实际作用是给测试类下的每一个测试方法单独包裹mock逻辑,mock的生效窗口为测试方法开始执行前到测试方法执行结束后。而setUp方法的调用时机在patch激活之前,所以setUp中运行的代码无法用到类装饰器声明的mock,只会调用真实的业务逻辑。
这也能解释你观察到的现象:把实例化逻辑放到测试方法内、或者在测试方法开头手动调用自定义初始化方法时,patch已经激活,mock就能正常生效。

解决方法

推荐优先使用在setUp中手动管理patch生命周期的方案,既可以保留setUp复用初始化逻辑的能力,也能保证mock在初始化阶段正常生效,代码示例如下:

import unittest
from unittest.mock import patch

class TestInitBase(unittest.TestCase):

    def setUp(self):
        """ Code that executes before every function. """
        # 第一步:启动所有mock补丁
        self.patches = [
            patch('geomet_data_registry.layer.base.get_today_and_now', new=mocked_get_date),
            patch('geomet_data_registry.layer.base.load_plugin', new=mocked_load_plugin),
            patch('geomet_data_registry.layer.base.TILEINDEX_PROVIDER_DEF', new=mocked_tileindex),
            patch('geomet_data_registry.layer.base.STORE_PROVIDER_DEF', new=mocked_store)
        ]
        for p in self.patches:
            p.start()

        # 第二步:执行原有初始化逻辑,此时mock已全部生效
        self.maxDiff = None
        self.today_date = \
            datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
        mocked_get_date.return_value = self.today_date
        self.base_layer = BaseLayer({'name': 'model_gem_global'})

    def tearDown(self):
        # 测试结束后统一停止所有补丁,避免影响其他测试
        for p in self.patches:
            p.stop()

    def test_Init(self):
        expected_values = {'items': [],...}
        base_layer_attr = self.base_layer.__dict__
        self.assertDictEqual(expected_values, base_layer_attr, msg=None)

如果不想调整patch的挂载方式,也可以选择保留类上的@patch装饰器,将需要依赖mock的初始化逻辑封装为普通方法,在每个测试方法开头手动调用,和你之前测试可行的mySetUp方案一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:06:06