Python单例改造后如何Mock模块函数,避免类初始化执行
解决单例模式下Mock类避免触发
__init__的方案 方案1:保留原有patch逻辑(推荐,零测试代码改动)
你之前的测试都是patch原始类path.to.some.module.MyClass,这个逻辑完全可以复用。核心思路是在单例初始化前完成patch,让单例拿到的是Mock类而非真实类,从根源上避免__init__执行。
如果用pytest,直接在conftest.py里加一个全局自动生效的fixture:
import pytest from unittest.mock import patch @pytest.fixture(autouse=True, scope="session") def mock_my_class(): # 提前patch原始类,覆盖所有测试会话 with patch('path.to.some.module.MyClass') as mock_cls: yield mock_cls
这样数百个原有测试无需任何修改,单例初始化时会自动使用Mock类,不会触发真实的初始化逻辑。
方案2:Mock单例的对外入口
如果不想全局patch,可以直接Mock暴露单例的入口函数(比如get_my_class),跳过单例内部的实例创建逻辑:
from unittest.mock import patch, Mock @patch('path.to.some.module.get_my_class') def test_example(mock_get): # 自定义Mock实例的行为 mock_instance = Mock() mock_instance.some_method.return_value = "test_output" mock_get.return_value = mock_instance # 执行测试逻辑 # ...
这种方式完全隔离真实类的初始化,不需要关心单例内部的_my_class属性。
为什么直接patchMyClassSingleton._my_class会触发__init__
因为单例的初始化逻辑(比如get_instance方法)会在属性为空时自动创建MyClass实例。当你patch_my_class时,若单例还未初始化,patch操作可能触发属性检查,间接调用了真实类的__init__;如果单例已在导入时初始化,patch只能替换现有实例,无法阻止之前的初始化。
内容的提问来源于stack exchange,提问作者Brendan
相关产品推荐
相关产品推荐

