[Bug]: Async function with multiple awaits never resolves when using fake timers
See original GitHub issueVersion
27.2.0
Steps to reproduce
- Clone my repo: https://github.com/srmagura/jest-timer-repro
yarn install
yarn test
Code:
import "jest";
beforeEach(() => {
jest.useFakeTimers();
});
function delay(duration: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, duration));
}
// PASS
it("delays", async () => {
const p = delay(100);
jest.runAllTimers();
expect(await p).toBeUndefined();
});
// PASS
it("delays once in a function", async () => {
async function f(): Promise<void> {
await delay(100);
}
const p = f();
jest.runAllTimers();
expect(await p).toBeUndefined();
});
// FAIL: Exceeded timeout of 5000 ms for a test.
it("delays twice in a function", async () => {
async function f(): Promise<void> {
await delay(100);
await delay(100);
}
const p = f();
jest.runAllTimers();
jest.runAllTimers();
jest.runAllTimers();
jest.runAllTimers();
expect(await p).toBeUndefined();
});
// PASS
it("delays twice in a function using real timers", async () => {
jest.useRealTimers();
async function f(): Promise<void> {
await delay(100);
await delay(100);
}
const p = f();
expect(await p).toBeUndefined();
});
Expected behavior
I expect all tests to pass. In the third test, jest.runAllTimers
should cause both delays to complete, and the promise returned by f
should resolve.
Actual behavior
The third test fails with
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."
Additional context
The result is same when using jest.useFakeTimers('legacy')
.
Environment
System:
OS: Windows 10 10.0.19043
CPU: (12) x64 AMD Ryzen 5 2600 Six-Core Processor
Binaries:
Node: 14.17.6 - C:\Program Files\nodejs\node.EXE
Yarn: 3.0.2 - ~\AppData\Roaming\npm\yarn.CMD
npm: 7.23.0 - C:\Program Files\nodejs\npm.CMD
npmPackages:
jest: ^27.2.0 => 27.2.0
Issue Analytics
- State:
- Created 2 years ago
- Reactions:7
- Comments:5
Top Results From Across the Web
Jest: Timer and Promise don't work well. (setTimeout and ...
But calling await Promise.resolve() only seems to resolve one pending promise. In the real world, testing functions having multiple asynchronous ...
Read more >Async Methods - Testing Library
Several utilities are provided for dealing with asynchronous code. These can be useful to wait for an element to appear or disappear in...
Read more >Async/await - The Modern JavaScript Tutorial
Here's an example with a promise that resolves in 1 second: async function f() { let promise = new Promise((resolve, reject) => {...
Read more >Asynchronous work - Jasmine Documentation
async functions implicitly return a promise. Jasmine will wait until the returned promise is either resolved or rejected before moving on to the...
Read more >Asynchronous JavaScript - Discover three.js!
Fortunately, there's a function that allows us to perform a very simple asynchronous operation, called setTimeout . This method takes two arguments, a...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
This could be solvable if jest exposed the
async
counterparts of@sinonjs/fake-timers
methods - the'modern'
implementation of fake timers.Until that happens, it can be solved by using fake-timers directly:
OP is fixed via #12572 by using
advanceTimers: true
. Available in https://github.com/facebook/jest/releases/tag/v28.0.0-alpha.8