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

如何测试方法是否以指定参数被恰好调用指定次数(如一次)?

实现toHaveBeenCalledTimesWith断言方法

Jest原生没有直接提供同时检查特定参数调用次数的匹配器,但我们可以通过自定义扩展匹配器来实现需求——统计mock函数以指定参数被调用的次数,并验证是否等于预期的N次(不关心调用顺序)。

实现思路

  1. 校验目标是否为mock函数,确保后续能获取调用记录
  2. 从mock函数的mock.calls中提取所有调用参数
  3. 用Jest内置的深度比对方法,筛选出和目标参数匹配的调用
  4. 统计匹配次数,和预期次数做对比,返回断言结果

自定义匹配器代码

在测试文件或Jest全局配置文件(如setupTests.js)中添加以下代码:

expect.extend({
  toHaveBeenCalledTimesWith(received, expectedTimes, ...expectedArgs) {
    // 校验是否为mock函数
    if (!received.mock) {
      return {
        pass: false,
        message: () => '必须传入mock函数'
      };
    }

    // 统计匹配指定参数的调用次数
    const matchingCallCount = received.mock.calls.filter(call => {
      return this.equals(call, expectedArgs);
    }).length;

    // 返回断言结果
    if (matchingCallCount === expectedTimes) {
      return {
        pass: true,
        message: () => `预期mock函数不会以${this.utils.printExpected(expectedArgs)}被调用${expectedTimes}次,但实际符合`
      };
    } else {
      return {
        pass: false,
        message: () => `预期mock函数以${this.utils.printExpected(expectedArgs)}被调用${expectedTimes}次,但实际被调用了${matchingCallCount}次`
      };
    }
  }
});

使用示例

假设我们有一个mock函数,要验证它以['user1', 25]为参数被调用恰好2次:

test('验证mock函数的特定参数调用次数', () => {
  const userLogger = jest.fn();
  userLogger('user1', 25);
  userLogger('user2', 30);
  userLogger('user1', 25);

  // 验证以['user1',25]调用的次数是否为2
  expect(userLogger).toHaveBeenCalledTimesWith(2, 'user1', 25);
  // 验证以['user2',30]调用的次数是否为1
  expect(userLogger).toHaveBeenCalledTimesWith(1, 'user2', 30);
});

补充说明

  • 匹配器使用this.equals做深度比对,和Jest原生toHaveBeenCalledWith的参数匹配逻辑完全一致,支持对象、数组等复杂参数的校验
  • 如果将匹配器代码放到全局配置文件中,所有测试文件无需重复定义即可直接使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:40:12