Jest test setTimeout and Promise


If you have a Jest test that calls setTimeout and Promise:

// timeout-promise.test.js
jest.useFakeTimers();

const utils = {
  async timeout(seconds) {
    await Promise.resolve((resolve) => setTimeout(resolve, seconds * 1000));
  },
};

it('waits 1 second', async () => {
  await utils.timeout(1);
  // ...
});

The test will fail with the error:

thrown: "Exceeded timeout of 5000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

The solution is to remove jest.useFakeTimers and stub out timeout with jest.spyOn:

 // timeout-promise.test.js
-jest.useFakeTimers();

 const utils = {
   async timeout(seconds) {
     await Promise.resolve((resolve) => setTimeout(resolve, seconds * 1000));
   },
 };

 it('waits 1 second', async () => {
+  const timeoutSpy = jest.spyOn(utils, 'timeout').mockResolvedValueOnce();
   await utils.timeout(1);
   // ...
+  timeoutSpy.mockRestore();
 });

The updated test code will now pass:

// timeout-promise.test.js
const utils = {
  async timeout(seconds) {
    await Promise.resolve((resolve) => setTimeout(resolve, seconds * 1000));
  },
};

it('waits 1 second', async () => {
  const timeoutSpy = jest.spyOn(utils, 'timeout').mockResolvedValueOnce();
  await utils.timeout(1);
  // ...
  timeoutSpy.mockRestore();
});


Please support this site and join our Discord!