done是测试框架传入的回调函数,用于显式通知异步操作完成;必须用于无Promise返回的异步场景(如setTimeout、事件监听、回调风格API),需确保调用且仅调用一次,并正确传递错误。

在 JavaScript 的异步测试中(尤其是使用 Jest 或 Jasmine 等测试框架时),done 是一个由测试运行器传入的回调函数,用于**显式告诉测试框架:异步操作已完成,可以结束当前测试用例**。它主要用于那些无法自动检测完成时机的异步逻辑,比如手动触发的定时器、自定义事件、或未返回 Promise 的回调风格 API。
什么时候必须用 done?
当测试函数内部有异步操作,且该操作不返回 Promise,或你无法用 async/await 改写时,就需要 done 来避免测试“提前通过”或超时失败。
- 使用
setTimeout、setInterval - 调用 Node.js 回调风格的函数(如
fs.readFile(path, callback)) - 监听自定义事件(
emitter.on('event', () => { ... })) - 测试底层依赖回调的旧版库(如某些 WebSocket 客户端)
基本用法:传入 done 并在异步完成时调用它
在测试函数签名中声明 done 参数,并确保它在所有可能的执行路径中被调用一次(且仅一次):
test('should fetch user after delay', (done) => {
setTimeout(() => {
expect(1 + 1).toBe(2);
done(); // ✅ 告诉 Jest:测试完成
}, 100);
});
⚠️ 注意:done 不调用 → 测试超时(Jest 默认 5s);调用多次 → 报错 “done() called multiple times”;在同步错误后仍调用 → 可能掩盖真实错误。
立即学习“Java免费学习笔记(深入)”;
安全处理错误:用 try/catch 包裹断言,并在 catch 中调用 done
异步回调中抛出的错误不会被测试框架自动捕获,需手动传递给 done(传入错误作为参数):
test('should reject invalid input', (done) => {
someAsyncFunction('bad', (err, result) => {
try {
expect(err).toBeInstanceOf(Error);
expect(result).toBeUndefined();
done(); // ✅ 成功路径
} catch (error) {
done(error); // ✅ 失败路径:传 error,测试会失败并显示堆栈
}
});
});
替代方案:优先考虑 async/await + Promise
如果被测代码能返回 Promise(或可包装成 Promise),推荐不用 done,更简洁安全:
test('should fetch user with async/await', async () => {
const user = await fetchUser(); // 返回 Promise
expect(user.name).toBe('Alice');
}); // Jest 自动等待 Promise 完成
✅ 更易读、自动错误传播、无需手动管理 done 生命周期。
不复杂但容易忽略:只要异步逻辑没返回 Promise,又不能改写,done 就是可靠的兜底方式——关键是调用时机准确、错误不遗漏。


















