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

使用Jest的toHaveBeenNthCalledWith为何返回误导性反馈?

问题原因及修复方案

1. Received区域显示预期值而非实际调用值

这是Jest对象匹配的默认行为导致的:当你用toHaveBeenNthCalledWith断言嵌套对象(比如fetch请求的options.headers)时,Jest默认采用部分匹配策略——它会将你传入的预期对象与实际调用的对象合并后展示,而非直接输出原始的实际值。

举个具体场景:如果你写了这样的断言:

expect(fetch).toHaveBeenNthCalledWith(1, expect.anything(), {
  headers: { Authorization: "abcdefghijklm" }
});

Jest会判定你只关注Authorization这个请求头,因此在错误输出时,会把实际调用的headers和你预期的内容合并,导致Received区域里的Authorization显示成你写的预期值,哪怕实际请求的这个头完全不同。

修复方式:

  • 若需严格匹配整个options对象,用expect.equal()包裹:
    expect(fetch).toHaveBeenNthCalledWith(1, expect.anything(), expect.equal({
      headers: { Authorization: "abcdefghijklm", /* 其他必须匹配的头字段 */ }
    }));
    
  • 若仅需验证Authorization头,明确使用expect.objectContaining()声明部分匹配,这样Jest会正确展示实际的headers对象:
    expect(fetch).toHaveBeenNthCalledWith(1, expect.anything(), expect.objectContaining({
      headers: expect.objectContaining({
        Authorization: "abcdefghijklm"
      })
    }));
    

2. 显示3次fetch调用但仅列出2次

主要是以下两种情况:

  • 异步操作未等待完成:你的应用逻辑中可能存在延迟执行的fetch调用(比如放在Promise、setTimeout里),Jest统计调用次数时捕获到了这第三次,但生成错误输出时该调用还未执行完毕,因此没被列出来。
  • mock调用记录未重置:全局mock的fetch没有在每次测试后清空调用记录,比如未在afterEach钩子中调用fetch.mockClear()或fetch.mockReset(),导致上一次测试的调用记录被累积到当前测试中。

修复方式:

  • 确保测试等待所有异步操作完成:用async/await包裹应用逻辑的调用,或用jest.runAllTimers()处理定时器驱动的请求。
  • 添加mock重置钩子,避免跨测试干扰:
    afterEach(() => {
      fetch.mockClear();
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 08:25:11