断言异步操作抛错需用 await expect(...).rejects(推荐)或 return expect(...).rejects,不可用 tothrow() 直接包裹 async 函数;须 await 整个 rejects 链或显式 return promise,否则测试假通过。

在 JavaScript 单元测试中,断言异步操作抛出错误,关键在于正确处理 Promise 拒绝(reject)或 async 函数的 throw,并让测试框架能捕获它。直接用 expect(() => fn()).toThrow() 会失败,因为异步错误不会同步抛出。
用 async/await + expect(...).rejects(推荐)
这是 Jest 等现代测试框架原生支持的方式,语义清晰、写法简洁:
test('fetchUser 异步抛出错误', async () => {
await expect(fetchUser('invalid-id')).rejects.toThrow('Network error');
// 或更精确地匹配错误实例或消息
await expect(fetchUser('invalid-id')).rejects.toEqual(new Error('Network error'));
await expect(fetchUser('invalid-id')).rejects.toMatch(/network/i);
});
注意:必须 await 整个 expect(...).rejects 链,否则测试会提前通过(未等待 Promise 结束)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
用 return + expect(...).rejects(兼容 Promise 风格)
如果测试函数不声明 async,可显式 return 一个 Promise:
- 返回
expect(...).rejects断言本身(Jest 会自动等待) - 适用于老版本 Jest 或需显式控制 Promise 生命周期的场景
test('fetchUser 返回被拒绝的 Promise', () => {
return expect(fetchUser('invalid-id')).rejects.toThrow('404 Not Found');
});
手动 catch 错误并断言(通用但冗余)
适用于不支持 .rejects 的极简环境(如原生 Node.js test runner 旧版),但易出错,不推荐:
test('fetchUser 抛错时进入 catch', async () => {
let error;
try {
await fetchUser('invalid-id');
} catch (e) {
error = e;
}
expect(error).toBeInstanceOf(Error);
expect(error.message).toContain('timeout');
});
⚠️ 注意:漏掉 await、忘记赋值 error、或没写 expect 都会导致测试“假通过”。
避免常见陷阱
-
不要写
expect(async () => { await fn() }).toThrow()—— 这只是断言一个 async 函数本身不抛错(它永远不抛),而非其内部逻辑 -
不要在
async测试里漏掉await或return,否则测试可能在 Promise 完成前就结束 - 若被测函数使用
setTimeout或事件触发错误(非 Promise reject),需用done()回调方式(Jest 支持,但已不推荐)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










