Message "Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout"
Asked Answered
B

26

502

I'm using Puppeteer and Jest to run some front end tests.

My tests look as follows:

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, async () => {
      await page.waitForSelector(PROFILE.TAB);
      await page.click(PROFILE.TAB);
    }, 30000);
});

Sometimes, when I run the tests, everything works as expectedly. Other times, I get an error:

Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.

     at node_modules/jest-jasmine2/build/queue_runner.js:68:21 <br/>
     at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:633:19)

This is strange because:

  1. I specified the timeout to be 30000

  2. Whether or not I get this error is seemingly very random

Why is this happening?

Boob answered 2/4, 2018 at 0:34 Comment(7)
Which line is timing out?Druci
@Boob Could you provide a GitHub repo? It'll be easier and faster for us to provide you with a solution. :)Glaucoma
@Asool, any feedback on the answer I postedCherimoya
could it be that the test actually fails for the 30000ms but the error from jest simply don't include the value you passed? meaning, if you put 0ms time out, does jest error changes?Rural
I saw this error when I was debugging my tests. Stopping at a breakpoint caused to get this errorHairdo
this issue has surfaced again with jest v27+ see issue here: github.com/facebook/jest/issues/11607Schultz
I am getting same error when I even import render from @testing-library/react-native. There is not resolution yet. Can anyone help in this?Cracked
C
516

The timeout you specify here needs to be shorter than the default timeout.

The default timeout is 5000 and the framework by default is jasmine in case of jest. You can specify the timeout inside the test by adding

jest.setTimeout(30000);

But this would be specific to the test. Or you can set up the configuration file for the framework.

Configuring Jest

// jest.config.js
module.exports = {
  // setupTestFrameworkScriptFile has been deprecated in
  // favor of setupFilesAfterEnv in jest 24
  setupFilesAfterEnv: ['./jest.setup.js']
}

// jest.setup.js
jest.setTimeout(30000)

See also these threads:

setTimeout per test #5055

Make jasmine.DEFAULT_TIMEOUT_INTERVAL configurable #652

P.S.: The misspelling setupFilesAfterEnv (i.e. setupFileAfterEnv) will also throw the same error.

Cherimoya answered 16/4, 2018 at 18:58 Comment(5)
If we out jest.setTimeOut(10000) inside describe block, is it applied only to the test cases inside the describe block?Ellinger
@James where exactly do you put it? Ive put in test() before the expect() and still get the timeout error...Fondly
Adding this forced my test to hang until the timeout which made me realize that my controller method wasn't calling res.status(204).send(); only res.status(204); which was the source of the problem. Hope it helpsSalisbarry
In my case only putting jest.setTimeOut(10000) in describe helped me. Neither putting it inside test function body, nor specifying timeout as a test parameter it.only(nm, fn, 10000) worked.Hone
If your promise resolves before the default timeout but you still get this error, chances are you have jest.useFakeTimers() somewhere in the test file (not necessarily in the same it block). related github issue: github.com/facebook/jest/issues/7151Pigment
R
133

It should call the async/await when it is async from test.

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, async (done) => {
        await page.waitForSelector(PROFILE.TAB);
        await page.click(PROFILE.TAB);
        done();
    }, 30000);
});
Rensselaerite answered 26/6, 2018 at 6:27 Comment(6)
Why should we have done in an async function? Don't we simply return Promise or undefined?Hash
No, this isn't correct. You don't need to call done() since you are awaiting your promises or you could just return page.click. done() is used, at least in my case, primarily for testing with callbacks.Tympanites
Thanks guys, I have removed the done callback which is not needed.Freshet
isn't this the same code as in the original question now?Tailwind
The presence of a parameter (named done in this case) in the callback causes Jest to wait until this parameter is called. Its presence is significant even if it is not used.Antecedence
Strange. I used done() to stop having this issue!Clearness
D
109

The answer to this question has changed as Jest has evolved. Current answer (March 2019):

  1. You can override the timeout of any individual test by adding a third parameter to the it. I.e., it('runs slow', () => {...}, 9999)

  2. You can change the default using jest.setTimeout. To do this:

    // Configuration
    "setupFilesAfterEnv": [  // NOT setupFiles
        "./src/jest/defaultTimeout.js"
    ],
    

    and

    // File: src/jest/defaultTimeout.js
    /* Global jest */
    jest.setTimeout(1000)
    
  3. Like others have noted, and not directly related to this, done is not necessary with the async/await approach.

Dorindadorine answered 9/3, 2019 at 21:3 Comment(0)
E
91

This is a relatively new update, but it is much more straight forward. If you are using Jest 24.9.0 or higher you can just add testTimeout to your config:

// in jest.config.js
module.exports = {
  testTimeout: 30000
}
Elutriate answered 10/12, 2019 at 14:53 Comment(3)
To take affect, make sure to "jest --watch" again, if it is already running.Clavicytherium
I wish this was the accepted answer, way more simple than having to put this config in a separate file.Cowfish
This worked like a charm, also the jest.setTimeout as it's own line doesn't work.Allege
M
50

I would like to add (this is a bit long for a comment) that even with a timeout of 3000 my tests would still sometimes (randomly) fail with

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

Thanks to Tarun's great answer, I think the shortest way to fix a lot of tests is:

describe('Puppeteer tests', () => {
  beforeEach(() => {
    jest.setTimeout(10000);
  });

  test('Best Jest test fest', async () => {
    // Blah
  });
});
Moil answered 27/9, 2018 at 19:2 Comment(1)
You don't need to call jest.setTimeout() inside beforeEach, calling it once is enough for all tests.Molar
S
49

For Jest 24.9+, we just need to add --testTimeout on the command line:

--testTimeout= 10000 // Timeout of 10 seconds

The default timeout value is 5000 (5000 ms - 5 seconds). This will be applicable for all test cases.

Or if you want to give timeout to particular function only then you can use this syntax while declaring the test case.

test(name, fn, timeout)

Example

test('example', async () => {

}, 10000); // Timeout of 10 seconds (default is 5000 ms)
Singhal answered 20/11, 2020 at 4:54 Comment(2)
Both a space and an equal sign before the number seems like overspecification. Is it actually correct? Will it actually work as expected? (Not rhetorical questions.)Algarroba
@PeterMortensen You are right, the space is not necessary, as seen here. It should instead be --testTimeout=10000.Sikkim
F
31

For Jest 24.9+, you can also set the timeout from the command line by adding --testTimeout.

Here's an excerpt from its documentation:

--testTimeout=<number>
Default timeout of a test in milliseconds. Default value: 5000.

Functionalism answered 11/10, 2019 at 6:41 Comment(0)
P
28

Make sure to invoke done(); on callbacks or it simply won't pass the test.

beforeAll((done /* Call it or remove it */ ) => {
  done(); // Calling it
});

It applies to all other functions that have a done() callback.

Predict answered 27/1, 2019 at 7:21 Comment(0)
C
17

Yet another solution: set the timeout in the Jest configuration file, e.g.:

{ // ... other stuff here
    "testTimeout": 90000
}
Condemnation answered 26/8, 2020 at 13:11 Comment(0)
H
9

You can also get timeout errors based on silly typos. For example, this seemingly innocuous mistake:

describe('Something', () => {
  it('Should do something', () => {
    expect(1).toEqual(1)
  })

  it('Should do nothing', something_that_does_not_exist => {
    expect(1).toEqual(1)
  })
})

Produces the following error:

FAIL src/TestNothing.spec.js (5.427s)
  ● Something › Should do nothing

    Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
      
      at node_modules/jest-jasmine2/build/queue_runner.js:68:21
      at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:678:19)

While the code sample posted doesn't suffer from this, it might be a cause of failures elsewhere. Also note that I'm not setting a timeout for anything anywhere - either here or in the configuration. The 5000 ms is just the default setting.

Hamnet answered 10/11, 2020 at 17:17 Comment(3)
What is the mistake? The fact that you gave the callback a parameter something_that_does_not_exist?Lowlife
Yes. Giving functions extra unused parameters in JavaScript is normally pointless but benign. Here it's likely to produce the above confusing error.Hamnet
It Works For me, after removing done() methodUnbiased
A
9

Mar 14, 2022, Jest 27.5 documentation indicates a new process:

https://jestjs.io/docs/api#beforeallfn-timeout

Pass a second parameter to test with the number of msec before timeout. Works!

test('adds 1 + 2 to equal 3', () => {
    expect(3).toBe(3);
},30000);
Andreandrea answered 15/3, 2022 at 0:23 Comment(0)
O
7

I recently ran into this issue for a different reason: I was running some tests synchronously using jest -i, and it would just timeout. For whatever reasoning, running the same tests using jest --runInBand (even though -i is meant to be an alias) doesn't time out.

Okra answered 3/4, 2019 at 18:58 Comment(0)
L
7

test accepts a timeout argument. See https://jestjs.io/docs/api#testname-fn-timeout. Here is a sample:

async function wait(millis) {
  console.log(`sleeping for ${millis} milliseconds`);
  await new Promise(r => setTimeout(r, millis));
  console.log("woke up");
}
test('function', async () => {
  await wait(5000);
}, 70000);
Leach answered 27/3, 2022 at 15:15 Comment(0)
D
6
// In jest.setup.js
jest.setTimeout(30000)

If on Jest <= 23:

// In jest.config.js
module.exports = {
  setupTestFrameworkScriptFile: './jest.setup.js'
}

If on Jest > 23:

// In jest.config.js
module.exports = {
  setupFilesAfterEnv: ['./jest.setup.js']
}
Dovap answered 31/10, 2019 at 12:34 Comment(1)
Doing this doesn't work, I get an error (and others on this thread) regarding "jest undefined". We shouldn't have to import jest on a jest setup file...Allege
E
5

The timeout problem occurs when either the network is slow or many network calls are made using await. These scenarios exceed the default timeout, i.e., 5000 ms. To avoid the timeout error, simply increase the timeout of globals that support a timeout. A list of globals and their signature can be found here.

For Jest 24.9

Ergonomics answered 31/8, 2019 at 19:41 Comment(0)
M
5

Turns out if your expect assertions are wrong, it can sometimes spit out the exceeded timeout error message.

I was able to figure this out by putting console.log() statements in my promise callback and saw the console.log() statements were getting ran in the jest output. Once I fixed my expect assertions, the timeout error went away and tests worked.

I spent way too long to figure this out and hope this helps whoever needs to read this.

Milton answered 30/11, 2021 at 21:25 Comment(0)
E
3

For the jest versions greater than 27, you can add useRealTimers on the top of your spec file.

Here is the snippet

import { shortProcess, longProcess } from '../../src/index';

jest.useRealTimers();

describe(`something`, function () {
    it('should finish fine', async function () {
        await shortProcess();
        expect(1).toBe(1);
    });

    it('should fail with a timeout', async function () {
        await longProcess();
        expect(1).toBe(1);
    });

    it('should finish fine again', async function () {
        jest.setTimeout(10 * 1000);
        await longProcess();
        expect(1).toBe(1);
    }, 10000);
});

Find the github issue here on jest repository.

Emmy answered 8/7, 2022 at 16:40 Comment(0)
S
1

In case someone doesn't fix the problem use methods above. I fixed mine by surrounding the async func by an arrow function. As in:

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, (() => {
      async () => {
        await page.waitForSelector(PROFILE.TAB)
        await page.click(PROFILE.TAB)
      }
    })(), 30000);
});
Soy answered 8/11, 2019 at 16:30 Comment(1)
It seems to me that putting the arrow function around the async will not tell the test to wait for the test to complete, so while you may not get an error now, you'll have a test running outside of its thread and a) the whole test suite may complete before this test is done, not testing this code and b) future errors inside this test might show up during a different test in the suite, making your tests flaky and hard to maintain.Cahoot
C
1

In my case, this error started appearing randomly and wouldn't go away even after setting a timeout of 30000. Simply ending the process in the terminal and rerunning the tests resolved the issue for me. I have also removed the timeout and tests are still passing again.

Cinquefoil answered 5/6, 2020 at 8:17 Comment(1)
In my case there was an error in the service and it was not runningPoverty
K
1

This probably won't be terribly helpful to most people visiting this page, but when I was getting this error it had nothing to do with Jest. One of my method calls was getting an empty object and a null exception while running locally. Once I added a null check, the failing tests and console log in question disappeared.

if(response !== null){
    this.searchSubj.next(resp);
 }
 else {
    return;
 }
Kabul answered 13/1, 2022 at 20:43 Comment(0)
E
1

modify your jest.config.X like this , X could be your language ts or js

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  //add below line to timeout//
  testTimeout: 30000
};
Ecclesiastic answered 29/3, 2023 at 15:37 Comment(0)
I
0

For those who are looking for an explanation about jest --runInBand, you can go to the documentation.

Running Puppeteer in CI environments

GitHub - smooth-code/jest-puppeteer: Run your tests using Jest & Puppeteer

Ingate answered 11/4, 2019 at 14:35 Comment(0)
G
0

Dropping my 2 cents here, I had the same issue on dosen of jest unit test (not all of them) and I notice that all started after I added to jestSetup this polyfill for MutuationObservers:

if (!global.MutationObserver) {
    global.MutationObserver = function MutationObserverFun(callback) {
        this.observe = function(){};
        this.disconnect = function(){};
        this.trigger = (mockedMutationsList) => {
            callback(mockedMutationsList, this);
        };
    };
}

Once I removed it test start working again correctly. Hope helps someone .

Gaona answered 21/9, 2021 at 20:30 Comment(0)
L
0

My issue was that I was using Nodejs 12 with Sequelize (pg: 7.14 - Postgres client). Then I upgraded nodejs version to 16, so "Timeout" errors showed up:

Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout

After an hour of debugging, I found out that pg vesion 7 isn't compatible with node >= 14. Because of that, pg.connection hangs.

So my solution was: I upgrade pg version to 8

Libbielibbna answered 25/4, 2023 at 2:58 Comment(0)
P
0

If somebody is getting this error in render,fireEventAPI or any other API from @testing-library/react-native for testing try adding the following lines

afterEach(() => {... jest.useRealTimers(); });

inside your describe also add

jest.useFakeTimers()

in beforeEach Not sure about the reason but this worked for me

Parsifal answered 15/2 at 5:3 Comment(0)
O
-3

add this in your test, not much to explain

beforeEach(() => {
  jest.useFakeTimers()
  jest.setTimeout(100000)
})

afterEach(() => {
  jest.clearAllTimers()
})
Oblation answered 21/9, 2021 at 1:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.