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
相关产品推荐
相关产品推荐

