
Jest 的 toThrow() 断言必须接收一个函数(如箭头函数)作为参数,否则会因错误未被捕获而直接抛出,导致测试失败。本文详解正确写法、原理及典型误区。
jest 的 `tothrow()` 断言必须接收一个函数(如箭头函数)作为参数,否则会因错误未被捕获而直接抛出,导致测试失败。本文详解正确写法、原理及典型误区。
在 Jest 测试中,expect(...).toThrow() 并非直接作用于表达式结果,而是用于验证某个函数执行时是否抛出指定错误。关键在于:expect 接收的必须是一个可调用的函数,而非函数调用后的返回值。若直接写 expect(evaluate_expression("5/0")),Jest 会在断言执行前就立即调用该函数——此时错误被抛出但未被 Jest 捕获,测试进程中断,断言根本不会运行,从而报错(如 Error: Division by zero 未被捕获)。
✅ 正确写法是将待测逻辑包裹在匿名函数或箭头函数中:
test("division 0 is handled", () => {
expect(() => evaluate_expression("5/0")).toThrow('Division by zero');
});
这样,Jest 内部会安全地调用该函数,并监听其是否抛出匹配的错误(支持字符串、正则、Error 构造器或自定义类)。你也可以使用更严格的匹配方式:
// 匹配错误消息(正则)
expect(() => evaluate_expression("5/0")).toThrow(/division by zero/i);
// 匹配 Error 实例类型
expect(() => evaluate_expression("5/0")).toThrow(Error);
// 验证错误对象属性(需配合 .toThrow() 后链式调用)
expect(() => evaluate_expression("5/0")).toThrow('Division by zero');
⚠️ 常见误区提醒:
- ❌
expect(evaluate_expression("5/0")).toThrow(...)→ 错误提前抛出,测试崩溃; - ❌
expect(Promise.resolve().then(() => evaluate_expression("5/0"))).rejects.toThrow(...)→ 这是针对 Promise 拒绝的写法,而evaluate_expression是同步函数,无需 Promise 包装; - ✅ 所有同步异常断言均需函数包装;异步函数(返回 Promise)才应使用
.rejects.toThrow()。
此外,请确保被测函数 evaluate_expression 在测试环境中可访问(例如通过 export 导出并在测试文件中 import),且无依赖 DOM 的副作用(当前代码中 document.getElementById 在 Node 环境下会报错)。建议在单元测试中对 evaluate_expression 进行纯逻辑隔离,剥离 UI 操作(如 calculate() 中的 DOM 访问),以提升可测性与稳定性。
总结:toThrow() 的本质是「错误捕获断言」,不是「值匹配断言」;牢记「函数即契约」——只有把待测行为封装为函数,Jest 才能介入执行流程并完成断言。










