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

如何让Mock对象捕获所有方法调用并执行统一逻辑如调用计数

可以实现,我们可以利用unittest.mock.Mock动态生成属性的特性,通过自定义Mock子类,统一给所有动态生成的可调用属性(即方法)绑定相同的响应逻辑,不需要逐个配置每个方法的mock规则。

实现方案

1. 基础实现(用全局计数器)

from unittest import mock

call_counter = 0

# 统一的响应逻辑:累加计数器,也可以自定义返回值、其他副作用
def common_side_effect(*args, **kwargs):
    global call_counter
    call_counter += 1
    # 如果你需要所有方法返回统一值,直接在这里return即可,比如 return True

class UnifiedMock(mock.Mock):
    def __getattr__(self, name):
        # 调用父类方法获取动态生成的属性
        attr = super().__getattr__(name)
        # 只给非私有、可调用的属性绑定统一副作用
        if callable(attr) and not name.startswith("_"):
            # 避免重复绑定副作用
            if not hasattr(attr, "_side_effect_set"):
                attr.side_effect = common_side_effect
                attr._side_effect_set = True
        return attr

2. 优化实现(无全局变量,计数器封装在Mock实例内)

from unittest import mock

class UnifiedCountMock(mock.Mock):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 计数器作为实例属性,不需要全局变量
        self.total_call_count = 0

    def _count_call(self, *args, **kwargs):
        self.total_call_count += 1
        # 按需添加统一返回逻辑

    def __getattr__(self, name):
        attr = super().__getattr__(name)
        if callable(attr) and not name.startswith("_"):
            if not hasattr(attr, "_count_bound"):
                attr.side_effect = self._count_call
                attr._count_bound = True
        return attr

适配你的测试代码

替换你原来的mock创建逻辑即可,不需要修改其他测试代码:

def test_EventListener():
    # 用自定义的UnifiedMock替换原有的普通Mock
    fooMock = UnifiedMock()
    # 如果用优化版的实现,直接初始化即可:fooMock = UnifiedCountMock()

    eventListener = EventListener(fooMock)
    # 执行你的测试用例
    eventListener.consume(evt1)
    eventListener.consume(evt2)
    # ... 其他调用

    # 基础实现可以直接读全局的call_counter
    print(f"总调用次数:{call_counter}")
    # 优化版实现可以读实例属性
    # print(f"总调用次数:{fooMock.total_call_count}")

原理说明

unittest.mock.Mock在访问不存在的属性时,会自动创建一个新的Mock实例作为返回值。我们重写__getattr__方法,在返回动态生成的属性前,判断如果是可调用的方法类属性,就统一绑定我们预设的副作用逻辑,不管实际调用的是func_one还是func_two,或者Foo类未来新增的其他方法,都会自动触发统一的响应规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:57:03