javascript单元测试验证错误需分同步异步:同步用expect(() => fn()).tothrow(),异步用await expect(fn()).rejects.tothrow();手动try/catch适用于细粒度断言;须覆盖null、nan等非法输入。

前端开发中 JavaScript 单元测试要测函数是否抛出错误,关键不是“让它崩”,而是让测试框架主动捕获并验证——错误必须被断言工具看见,不能直接中断测试流程。
同步错误:用 toThrow 或 toThrowError 包裹函数调用
错误必须放在函数里传给 expect,不能直接执行。否则异常一出,测试就挂了,断言根本跑不到。
- ✅ 正确写法(Jest / Vitest):expect(() => divide(10, 0)).toThrow(/division by zero/)
- ✅ 验证错误类型更可靠:expect(() => parseJSON('{')).toThrowError(SyntaxError)
- ❌ 错误写法:expect(divide(10, 0)).toThrow() —— 这会先执行再断言,测试提前失败
异步错误:必须用 await + rejects
async 函数或返回 Promise 的代码出错,是 reject,不是 throw。用 toThrow 会完全失效。
- ✅ 正确写法:await expect(fetchUser('invalid')).rejects.toThrow('Network error')
- ✅ 校验自定义错误结构:await expect(apiCall()).rejects.toMatchObject({ code: 'TIMEOUT' })
- ❌ 错误写法:expect(() => apiCall()).toThrow() 或 expect(apiCall()).toThrow() —— 都不等待 Promise,断言无效
需要细粒度控制时:手动 try/catch + 显式断言
当你要检查错误堆栈、自定义属性(如 err.code)、或用 Chai 等不支持 toThrow 的断言库时,可以手动捕获。
- 确保 try 块里执行,catch 中做 expect;别忘了加兜底判断,防止没报错导致测试“静默通过”
- 示例:
let error;
try { unsafeOperation(); }
catch (e) { error = e; }
expect(error).toBeDefined();
expect(error).toBeInstanceOf(ValidationError);
expect(error.code).toBe('MISSING_FIELD');
覆盖典型非法输入,不只看“有没有错”
真正暴露防护漏洞的,是那些业务上不该接受却没拦住的输入:
- null、undefined、空字符串、0、false —— 检查是否和正常值被同等对待
- 类型错位:把字符串 '123' 当数字传、把对象当回调传
- 边界值:负数年龄、超长 ID、NaN 时间戳、Infinity 金额
- 格式违规:非法邮箱、非 ISO 日期、缺失必填字段的对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











