Last updated: Mar 7, 2024
Reading timeยท4 min

The mocha error Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. occurs for multiple reasons:
done() function when testing async code.To solve the error, make sure to call the done() function when testing async
code and increase your timeout if necessary.

Here is the complete stack trace.
1) tests the type of a thrown error: Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/borislav/Desktop/bobbyhadz-rest/bobbyhadz-js/test/index.test.js)
Here is an example of how the error occurs.
import assert from 'assert'; it('tests an async function', done => { const p = new Promise(resolve => setTimeout(() => resolve('success'), 3000), ); p.then(result => { assert(result === 'success'); done(); }).catch(done); });
The Promise is resolved after 3 seconds but the default mocha timeout is 2000
milliseconds (2 seconds).
If I run the test with npx mocha, it fails because the timeout is exceeded.
The first thing you should try is to exceed the timeout of your tests.
You can specify the --timeout flag when issuing the mocha command.
One way to increase your timeout is to update the test script in your
package.json file.
{ "scripts": { "test": "mocha --timeout 10000" } }
The example sets the timeout of your mocha tests to 10000 ms (10 seconds).
The next time you now issue the npm run test command, the timeout will be set
to 10 seconds instead of 2.
You can also specify the flag when running the command with npx.
npx mocha --timeout 10000

You can also set the timeout by calling the timeout() function on the object
that is returned from the it() function.
import assert from 'assert'; it('tests an async function', done => { const p = new Promise(resolve => setTimeout(() => resolve('success'), 3000), ); p.then(result => { assert(result === 'success'); done(); }).catch(done); }).timeout(10000); // ๐๏ธ specify timeout here
If you run your mocha command, the timeout will be set to 10 seconds for the
specific test.
If you convert your arrow function to a named function, you can also set the
timeout on the this object.
import assert from 'assert'; // ๐๏ธ using a named function (NOT arrow) it('tests an async function', function (done) { // ๐๏ธ set timeout here this.timeout(10000); const p = new Promise(resolve => setTimeout(() => resolve('success'), 3000), ); p.then(result => { assert(result === 'success'); done(); }).catch(done); });
Notice that we didn't use an arrow function to be able to access properties on
the this object.
If you pass an arrow function as the second argument to it, then the this
keyword will be undefined.
This example also sets the timeout for the specific test.
done() function after your assertionsMake sure to call the done() function after your assertions.
import assert from 'assert'; it('tests an async function', done => { const p = Promise.resolve('success'); p.then(result => { assert(result === 'success'); // ๐๏ธ call done here done(); }).catch(done); });
The callback function we passed to it() takes the done() function as a
parameter.
The done function is used to indicate to mocha that we're done testing the
async code.
async/await syntax to test your codeAn alternative approach is to use the async/await syntax to test your code.
import assert from 'assert'; it('tests an async function', async () => { const p = Promise.resolve('success'); const result = await p; assert(result === 'success'); });
We marked the callback function as
async to be able to use the
await keyword to await Promises.
The result variable stores the
resolved value.
Notice that we didn't have to call the done() function when using the
async/await syntax.
If your function takes the done argument and doesn't call it, the test will
fail.
import assert from 'assert'; // ๐๏ธ takes done it('tests async code', async done => { const p = Promise.reject('success'); const result = await p; assert(result === 'success'); });
The test above fails with the following error message:
The reason the test fails is that the callback function takes the done
argument and doesn't call it.
Make sure to remove the done argument when testing async code with
async/await.
Removing the done argument resolves the issue.
import assert from 'assert'; // โ Test passes it('tests async code', async () => { const p = Promise.resolve('success'); const result = await p; assert(result === 'success'); });
If you take the done() argument in an async/await function and try to call
it, you'd get the following error:
import assert from 'assert'; it('tests async code', async done => { const p = Promise.resolve('success'); const result = await p; assert(result === 'success'); // โ๏ธ Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both. done(); });
To solve the error, remove the done argument from the callback function.
The done argument should only be used with the .then() syntax and callbacks
when testing async code.
If you use the async/await syntax, you don't have to use done().
Basically, when you await your Promises, mocha knows when your tests end.
On the other hand, when you use callbacks, you have to inform mocha when your
test ends using done().
You can learn more about the related topics by checking out the following tutorials: