Jest: Exceeded timeout of 5000 ms for a test. Add a timeout value to this test

avatar
Borislav Hadzhiev

Last updated: Mar 7, 2024
6 min

banner

# Table of Contents

  1. Jest: Exceeded timeout of 5000 ms for a test. Add a timeout value to this test
  2. Increasing the timeout for your Jest test
  3. Using the done() function in your async tests
  4. Testing asynchronous code with resolves
  5. Try calling jest.useRealTimers()

# Jest: Exceeded timeout of 5000 ms for a test. Add a timeout value to this test

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.

jest exceeded timeout of 5000 ms for test

Here is the complete stack trace:

shell
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."

# Increasing the timeout for your Jest test

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.

index.test.js
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.

index.test.js
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.

test passes after timeout increase

If you need to increase your Jest timeout globally:

  1. Create a jest.config.cjs file in the root directory of your project (next to your package.json file).
jest.config.cjs
/** @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.

  1. Create a jest.setup.js file right next to your jest.config.cjs file.
jest.setup.js
jest.setTimeout(30000);

increase jest timeout globally

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.

jest.config.cjs
/** @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.

shell
npx jest --testTimeout=30000

increase jest timeout with testtimeout flag

You can also update the test script in your package.json file to not have to remember to set the flag.

package.json
{ "scripts": { "test": "jest --testTimeout=30000" } }

Now when you issue the npm run test command, your Jest timeout will be set to 30 seconds globally.

# Using the done() function in your async tests

Make 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.

index.test.js
// ๐Ÿ‘‡๏ธ 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.

All functions that are marked as 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:

  1. Remove the done argument.
  2. Use the .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.

index.test.js
// ๐Ÿ‘‡๏ธ 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.

index.test.js
// ๐Ÿ‘‡๏ธ 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.

# Testing asynchronous code with resolves

You can also use the resolves matcher to test your async code.

index.test.js
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.

index.js
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).

# Try calling 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.

index.test.js
jest.useRealTimers();

You can also try to call the useFakeTimers function with the legacy string.

index.js
jest.useFakeTimers('legacy')

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev