如何Mock导入阶段执行的函数?含ABC类多方法Mock场景
如何Mock导入阶段自动执行的类初始化与方法调用
当导入xyz.py时,代码会自动实例化ABC类并调用obj.print_1(),导致输出"making object"和"printed 1"。要Mock__init__()、print_1()和print_2()这三个方法,核心是在导入xyz.py之前完成Mock配置,避免原代码的副作用。
以下是基于Python标准库unittest.mock的具体实现方案:
步骤1:提前Mock ABC类
由于xyz.py在导入阶段就会执行实例化和方法调用,必须先替换abc模块中的ABC类为Mock对象,再导入xyz。
示例测试代码
from unittest.mock import patch, MagicMock # 用patch上下文管理器替换abc.ABC类 with patch('abc.ABC') as mock_abc_cls: # 获取Mock类的实例对象(对应xyz里的obj) mock_obj = mock_abc_cls.return_value # 分别Mock三个方法,屏蔽原方法的print输出 mock_obj.__init__ = MagicMock(return_value=None) mock_obj.print_1 = MagicMock(return_value=None) mock_obj.print_2 = MagicMock(return_value=None) # 此时导入xyz,执行的是Mock后的逻辑 import xyz # 验证调用行为(可选) mock_abc_cls.assert_called_once() # 确认ABC()被实例化一次 mock_obj.print_1.assert_called_once() # 确认print_1()被调用一次 # 测试func(),验证print_2的调用参数 xyz.func() mock_obj.print_2.assert_called_once_with(2)
关键细节说明
patch('abc.ABC')会拦截xyz.py中from abc import ABC的导入逻辑,让它拿到的是Mock类而非原类。mock_abc_cls.return_value对应Mock类实例化后的对象,也就是xyz.py里的obj,直接替换它的三个方法为MagicMock,就能完全控制方法的行为。- 必须在
import xyz前完成所有Mock配置,否则原代码的实例化和方法调用已经执行,Mock会失去作用。
非测试场景的用法
如果不是在测试代码中,而是在业务脚本里需要Mock,也可以用类似方式:
from unittest.mock import patch, MagicMock # 先创建Mock实例并配置方法 mock_obj = MagicMock() mock_obj.__init__ = MagicMock() mock_obj.print_1 = MagicMock() mock_obj.print_2 = MagicMock() # 替换abc.ABC为返回该Mock实例的Mock类 with patch('abc.ABC', return_value=mock_obj): import xyz # 后续可以直接操作mock_obj,比如断言调用或修改返回值
内容的提问来源于stack exchange,提问作者Amogh Mishra
相关产品推荐
相关产品推荐

