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

