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

The Jest error "Exceeded timeout of 5000 ms for a test. Add a timeout value to this test to increase the timeout, if this is a long-running test" occurs when you exceed the timeout of 5 seconds for a Jest test.
To solve the error, increase jest's timeout for the test or globally and make sure your Promise resolves.

Here is the complete stack trace:
thrown: "Exceeded timeout of 5000 ms for a test. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."
The default timeout for a Jest test is 5000 ms (5 seconds).
If a test exceeds the timeout, it automatically fails, even if the Promise would've resolved after 6 seconds.
For example, the following test fails.
it('tests async code', async () => { const employeeData = {id: 1, name: 'bobby hadz', salary: 500}; // ๐๏ธ This resolves after 6 seconds const employeePromise = new Promise(resolve => setTimeout(() => resolve(employeeData), 6000), ); const result = await employeePromise; expect(result.id).toBe(1); expect(result.name).toBe('bobby hadz'); expect(result).toEqual(employeeData); });
The Promise in the example resolves after 6 seconds, so it exceeds the default timeout of 5 seconds and the test fails.
One way to resolve the issue is to increase the timeout for the specific test.
You can pass a third argument to the it() or test() functions - the timeout
for the test in milliseconds.
it('tests async code', async () => { const employeeData = {id: 1, name: 'bobby hadz', salary: 500}; const employeePromise = new Promise(resolve => setTimeout(() => resolve(employeeData), 6000), ); const result = await employeePromise; expect(result.id).toBe(1); expect(result.name).toBe('bobby hadz'); expect(result).toEqual(employeeData); }, 30000); // ๐๏ธ increase timeout to 30 seconds
I passed a third argument of 30000 to the it() function to increase the
timeout of the specific test to 30 seconds.
If I run the test now, it passes.

If you need to increase your Jest timeout globally:
jest.config.cjs file in the root directory of your project (next
to your package.json file)./** @type {import('jest').Config} */ const config = { setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], }; module.exports = config;
Make sure you don't misspell the setupFilesAfterEnv configuration key as this
also causes difficult-to-debug errors.
jest.setup.js file right next to your jest.config.cjs file.jest.setTimeout(30000);

Notice that the jest.config.cjs file has a .cjs extension (CommonJS).
You could also try to set the file's extension to .js, however, you'd most
likely get the
Module is not defined in ES module scope
error.
If you don't want to define a separate jest.setup.js file, you can increase
the timeout directly in your jest.config.cjs file.
/** @type {import('jest').Config} */ const config = { testTimeout: 30000, }; module.exports = config;
The testTimeout property can be set directly on the Jest config object that
you export from jest.config.cjs.
This approach increases the default Jest timeout to 30 seconds for all tests.
You don't have to pass a third argument to the it() or test() functions
unless you want to change the default of 30 seconds.
You can also set your Jest timeout with the --testTimeout flag.
npx jest --testTimeout=30000

You can also update the test script in your package.json file to not have to
remember to set the flag.
{ "scripts": { "test": "jest --testTimeout=30000" } }
Now when you issue the npm run test command, your Jest timeout will be set to
30 seconds globally.
done() function in your async testsMake sure you aren't using the done() function in tests that use the
async/await syntax.
For example, the following code sample causes an error.
// ๐๏ธ test takes a `done` function (marked async) it('tests async code', async done => { const employeeData = {id: 1, name: 'bobby hadz', salary: 500}; const employeePromise = new Promise(resolve => setTimeout(() => resolve(employeeData), 6000), ); const result = await employeePromise; expect(result.id).toBe(1); expect(result.name).toBe('bobby hadz'); expect(result).toEqual(employeeData); // โ๏ธ Test functions cannot both take a 'done' callback and return something. Either use a 'done' callback or return a promise. // calls done() function done(); }, 30000);
The test takes the done function but uses the async/await syntax which is
not allowed.
async return a Promise even if you don't explicitly return a value from the function.This is not allowed when taking the done function as an argument.
In this case, you have 2 options:
done argument..then() syntax or callbacks and call done() after your
assertions.Here is an example of a test that passes and uses the done() function with the
.then() syntax.
// ๐๏ธ takes the done function it('tests async code', done => { const employeeData = {id: 1, name: 'bobby hadz', salary: 500}; const employeePromise = new Promise(resolve => setTimeout(() => resolve(employeeData), 6000), ); employeePromise.then(result => { expect(result.id).toBe(1); expect(result.name).toBe('bobby hadz'); expect(result).toEqual(employeeData); // ๐๏ธ calls the done() function after all assertions done(); }); }, 30000);
The test takes the done function and calls it after all assertions.
Once your callback function defines the done argument, Jest waits for you to
call it to pass or fail your test.
You either have to call done() or remove it otherwise, Jest is stuck on that
particular test.
The done argument doesn't even have to be called done for it to fail your
times due to a timeout.
For example, the following test fails due to a timeout.
// ๐๏ธ defined the done() argument under another name it('tests async code', DEFINED_THIS_BY_MISTAKE => { const employeeData = {id: 1, name: 'bobby hadz', salary: 500}; const employeePromise = new Promise(resolve => setTimeout(() => resolve(employeeData), 6000), ); employeePromise.then(result => { expect(result.id).toBe(1); expect(result.name).toBe('bobby hadz'); expect(result).toEqual(employeeData); }); }, 30000);
The callback function I passed to it() takes the done function as an
argument even though the argument is not called done.
As previously noted, you either have to remove the argument or call the done()
function, otherwise, Jest times your test out.
resolvesYou can also use the resolves matcher to test your async code.
it('tests async code', async () => { const employeeData = {id: 1, name: 'bobby hadz', salary: 500}; const employeePromise = new Promise(resolve => setTimeout(() => resolve(employeeData), 6000), ); await expect(employeePromise).resolves.toEqual(employeeData); }, 30000);
The example uses the
resolves matcher with
the async/await syntax but you can also use it with .then().
When the resolves matcher is used in your expect statement, Jest will wait
for the Promise to resolve.
If the promise is rejected, the test will automatically fail.
However, note that you have to return the assertion, otherwise, your test will
complete before the Promise is resolved.
it('tests async code', () => { const employeeData = {id: 1, name: 'bobby hadz', salary: 500}; const employeePromise = new Promise(resolve => setTimeout(() => resolve(employeeData), 6000), ); return expect(employeePromise).resolves.toEqual(employeeData); }, 30000);
Notice that I returned the assertion.
This way Jest knows to wait for the Promise to be resolved/rejected.
I've also written a detailed guide on how to test exceptions in Jest (sync and async).
jest.useRealTimers()Jest timeout errors are also caused if you enable fake timers in your tests.
Fake timers are enabled by calling jest.useFakeTimers() and replace the
original implementation of setTimeout() and other timer functions.
This can sometimes cause issues with timeout errors.
Try to add the following line at the top of your test file.
jest.useRealTimers();
You can also try to call the useFakeTimers function with the legacy string.
jest.useFakeTimers('legacy')
You can learn more about the related topics by checking out the following tutorials: