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

Jest中测试Mock抛出异常时rejects.toThrow断言失败的问题排查

Jest中测试Mock抛出异常时rejects.toThrow断言失败的问题排查

我帮你排查了这个问题,核心原因在于rejects.toThrow()的判断逻辑和你Mock抛出的值类型不匹配:

问题分析

你当前用inner.mockRejectedValue('Error')让Mock返回了一个被字符串'Error'拒绝的Promise,而Jest的rejects.toThrow()断言默认是期望被拒绝的值是一个Error类的实例(或者继承自Error的对象),它会严格校验是否是标准错误对象,而非普通字符串。

你的第一个try/catch能通过,是因为try/catch会捕获所有Promise拒绝的值(不管是字符串还是Error实例),但rejects.toThrow()有更严格的校验规则,所以第二个断言直接失败了。

两种解决方案

你可以根据需求选择任意一种方案修复:

方案1:让Mock抛出标准Error实例

把Mock拒绝的值改成Error对象,这样rejects.toThrow()就能正常匹配:

import { jest } from '@jest/globals';

const inner = jest.fn();
const underTest = async () => await inner();

test('async mock throws within async function', async () => {
  // 改成抛出Error实例
  inner.mockRejectedValue(new Error('Error'));

  try {
    await underTest();
    expect('Should not reach this statement').toBeUndefined();
  } catch (err) {
    expect(err.message).toEqual('Error');
  }
  // 现在这个断言可以正常通过
  await expect(underTest()).rejects.toThrow();
  // 也可以指定匹配错误消息
  await expect(underTest()).rejects.toThrow('Error');
});

方案2:调整断言匹配Mock的实际拒绝值

如果你确实需要Mock拒绝普通字符串,那可以把断言改成匹配具体的值,而不是用toThrow():

import { jest } from '@jest/globals';

const inner = jest.fn();
const underTest = async () => await inner();

test('async mock throws within async function', async () => {
  inner.mockRejectedValue('Error');

  try {
    await underTest();
    expect('Should not reach this statement').toBeUndefined();
  } catch (err) {
    expect(err).toEqual('Error');
  }
  // 用toEqual匹配实际拒绝的字符串
  await expect(underTest()).rejects.toEqual('Error');
});

额外说明

Jest的rejects.toThrow()还有这些细节:

  • 如果不传参数,它只会校验被拒绝的是Error实例;
  • 如果传字符串参数,它会校验Error实例的message属性是否匹配该字符串;
  • 如果传正则表达式,它会校验Error的message是否匹配该正则;
  • 如果传构造函数(比如TypeError),它会校验被拒绝的是该构造函数的实例。

备注:内容来源于stack exchange,提问作者Antonio Pérez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:13:12