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

如何用Jest模拟非异步方法抛出异常?

问题分析与修复方案

嗨,这个问题其实是Jest断言toThrowError的一个常见使用误区,我来给你拆解清楚:

为什么直接调用会触发测试失败?

你现在写的expect(myController.create(data)).toThrowError(Error)有个关键问题:JavaScript会先执行myController.create(data),再把执行结果传给expect。而你已经把myService.create模拟成抛出错误,所以这个调用会立刻抛出错误,Jest还没来得及运行断言逻辑,就捕获到了未处理的错误,直接标记测试失败。

正确的写法应该是这样

toThrowError要求你把待测试的函数本身传递给expect,而不是函数执行后的结果。Jest会帮你包裹这个函数并执行,同时内部捕获抛出的错误,完成断言。修改后的测试代码如下:

it("should fail due to any 'MyService' error", () => {
  jest.spyOn(myService, 'create').mockImplementation(() => {
    throw new Error();
  });
  // 这里把调用包装成一个箭头函数传给expect
  expect(() => myController.create(data)).toThrowError(Error);
});

关于try/catch的“正常”运行

你用try/catch包裹时,相当于自己手动捕获了myController.create(data)抛出的错误,避免了Jest检测到未处理的错误,所以测试不会直接失败。但这其实是一种“伪正常”——你并没有真正让toThrowError完成断言逻辑,只是绕过了错误而已,并不是正确的测试姿势。

补充说明

因为你的create方法是同步的,所以上面的同步写法完全适用。如果是异步方法,写法会变成expect(myController.create(data)).rejects.toThrowError(Error),不过你的场景用不上这个~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:09:53