Mocha "Ensure the done() callback is being called" timeout in CI
Mocha waited the default 2000 ms for an async test to finish and it never did. The hint tells you exactly why: the test neither called done() nor returned the promise Mocha could await.
What this error means
An async test fails with "Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure \"done()\" is called; if returning a Promise, ensure it resolves." It is often flakier in CI on a slower runner.
1) loads config
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is
called; if returning a Promise, ensure it resolves.
(/home/runner/work/app/test/config.test.js)Common causes
done() is never called
The test takes a done parameter but a branch (an error, an early return) skips calling it, so Mocha waits until the timeout.
A returned promise that never resolves
The async function awaits work that hangs in CI, so the promise Mocha is waiting on never settles.
How to fix it
Return a promise or call done on every path
- Prefer
async/awaitand return the promise instead of usingdone. - If you keep
done, call it in success and error branches. - Mock slow dependencies so the test does not hang on real I/O.
it('loads config', async () => {
const cfg = await loadConfig();
expect(cfg.port).to.equal(3000);
});Raise the timeout for slow work
For a genuinely slow test, increase its timeout rather than leaving it at 2000 ms.
it('slow', async function () {
this.timeout(15000);
// ...
});How to prevent it
- Use async/await and return promises instead of the
donecallback. - Mock external I/O so tests do not depend on real timing.
- Set per-test timeouts for legitimately slow tests.