done是测试框架用于显式通知异步操作完成的回调函数,必须在手动管理的异步场景(如settimeout、事件监听、回调型api)中调用,且仅在最终完成分支调用一次;推荐优先使用async/await替代。

在 JavaScript 异步测试中,done 是 Jest、Jasmine 等测试框架提供的回调函数,用于显式告诉测试运行器:异步操作已完成,可以结束当前测试用例。不调用 done 会导致测试超时失败;调用过早或多次则可能引发误判。
什么时候必须用 done
当测试逻辑包含手动管理的异步操作(如 setTimeout、setInterval、原生 Promise 链未返回、事件监听、或底层无 Promise 封装的 API)时,框架无法自动感知完成时机,需靠 done 显式通知。
- 使用
setTimeout或setImmediate的场景 - 监听自定义事件(如
element.addEventListener('loaded', ...)) - 调用没有返回 Promise 的回调型 API(如 Node.js 的
fs.readFile(path, callback)) - 手动创建未返回的 Promise(如忘记
return new Promise(...))
正确使用 done 的写法
将 done 作为测试函数的参数传入,在异步操作的**最终完成分支**里调用它。若操作可能出错,应在 catch 或错误回调中调用 done.fail()(Jasmine)或 done(error)(Jest)来标记失败。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- Jest 示例:
test('should fetch user after delay', (done) => {
setTimeout(() => {
expect(1 + 1).toBe(2);
done(); // ✅ 正确:操作完成时调用
}, 100);
}); - Jasmine 示例:
it('should handle error gracefully', function(done) {
fs.readFile('missing.txt', 'utf8', (err, data) => {
if (err) {
done.fail(err); // ✅ 错误时通知失败
} else {
expect(data).toBeDefined();
done(); // ✅ 成功时通知完成
}
});
});
常见错误和避坑点
done 不是“可选语法糖”,而是异步控制的关键开关。以下做法容易导致测试不稳定:
- 忘记调用
done()→ 测试卡住,最终超时失败 - 在条件分支外提前调用(如放在
if外但逻辑只在else中执行)→ 测试过早结束,断言未执行 - 同一测试中多次调用
done()→ Jest 报done() called multiple times,Jasmine 可能静默忽略后续调用 - 用
async/await却还传done→ 冲突,应二选一:要么纯async函数(自动等待 Promise),要么用done回调风格
替代方案:优先考虑 async/await
对返回 Promise 的异步操作(如 fetch、axios.get、new Promise),直接 return 或用 async/await 更简洁安全,无需 done。
- ✅ 推荐:
test('fetches user', async () => {
const res = await fetch('/api/user');
const user = await res.json();
expect(user.name).toBe('Alice');
}); - ❌ 不必要地混用:
test('fetches user', (done) => {
fetch('/api/user').then(res => res.json()).then(user => {
expect(user.name).toBe('Alice');
done(); // 完全可用,但不如 async/await 直观
});
});
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










