
Jest 的 toThrow() 断言要求被测代码必须包裹在函数中执行,否则错误会直接抛出导致测试崩溃;本文详解正确写法、原理分析与实战注意事项。
jest 的 `tothrow()` 断言要求被测代码必须包裹在函数中执行,否则错误会直接抛出导致测试崩溃;本文详解正确写法、原理分析与实战注意事项。
在 Jest 测试中,expect(...).toThrow() 并非直接接收一个表达式的结果,而是必须接收一个函数(即“可执行的代码块”),以便 Jest 能在其内部 try...catch 机制中捕获异常。若直接传入 evaluate_expression("5/0")(如 expect(evaluate_expression("5/0")).toThrow(...)),该函数会立即执行——一旦抛出错误,Jest 尚未介入捕获,测试进程便中断,断言根本无法运行,最终报错类似 Error: expect(received).toThrow(expected) 或 thrown error not caught。
✅ 正确写法是使用箭头函数或匿名函数包裹调用:
test("division 0 is handled", () => {
expect(() => evaluate_expression("5/0")).toThrow('Division by zero');
});
这样,Jest 才能在受控环境中调用该函数,并捕获其同步抛出的 Error 实例。注意:toThrow() 支持多种匹配方式:
-
.toThrow():仅检查是否抛出任意错误; -
.toThrow('Division by zero'):精确匹配错误消息字符串; -
.toThrow(/division/i):支持正则匹配(忽略大小写); -
.toThrow(expect.any(Error)):验证是否为 Error 类型实例。
⚠️ 常见误区提醒:
- ❌ 不要加
await或.then():toThrow()仅处理同步错误;若待测函数返回 Promise 并reject,应改用expect(asyncFn()).rejects.toThrow(...); - ❌ 不要省略括号:
expect(evaluate_expression)是在检查函数本身(不会执行),而非其行为; - ✅ 确保错误确实被抛出:你的
evaluate_expression中throw new Error('Division by zero')逻辑正确,但需确认该分支在"5/0"输入下必然触发(例如tokens解析是否准确?b是否确实为0?建议在测试前加console.log或使用debugger验证执行流)。
最后,完整修复后的测试套件示例如下:
describe('operate', () => {
test("works with addition", () => {
expect(evaluate_expression("3+5")).toEqual(8);
});
test("works with subtraction", () => {
expect(evaluate_expression("128-29")).toEqual(99);
});
test("works with multiplication", () => {
expect(evaluate_expression("25*5")).toEqual(125);
});
test("works with division", () => {
expect(evaluate_expression("990/99")).toEqual(10);
});
test("division by zero is handled", () => {
expect(() => evaluate_expression("5/0")).toThrow('Division by zero');
});
});
掌握这一关键规则,可避免 90% 以上的 toThrow() 失效问题,让异常处理逻辑得到真正可靠的单元覆盖。










