Jest Async Test Timeout Exceeded Fix
In this tutorial, you'll learn about Jest Async Test Timeout Exceeded Fix. We cover key concepts, practical examples, and best practices.
Jest throws Timeout - Async callback was not invoked within the 5000 ms timeout — your async test never resolved and Jest timed out waiting.
The Problem
// WRONG — async test with missing await
test('fetches user data', () => {
return fetchUser().then(data => {
expect(data.name).toBe('Alice');
});
// Missing return statement:
fetchUser().then(data => {
expect(data.name).toBe('Alice');
});
});
Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.
The second call to fetchUser() creates a promise that Jest doesn't wait for — the test passes an empty synchronous function, Jest marks it as done, and the assertion never runs.
Step-by-Step Fix
1. Return the promise or use async/await
// RIGHT — return the promise
test('fetches user data', () => {
return fetchUser().then(data => {
expect(data.name).toBe('Alice');
});
});
// RIGHT — use async/await
test('fetches user data', async () => {
const data = await fetchUser();
expect(data.name).toBe('Alice');
});
2. Increase the timeout for slow operations
// RIGHT — increase timeout for slow async operations
test('processes large dataset', async () => {
const result = await processLargeDataset();
expect(result.length).toBe(10000);
}, 30000); // 30 seconds
Or set it globally:
// In setupFiles or test file
jest.setTimeout(30000);
3. Handle the done callback properly
// WRONG — done is never called on error
test('reads file', (done) => {
fs.readFile('/tmp/data.txt', 'utf8', (err, data) => {
if (err) throw err;
expect(data).toContain('test');
done();
});
});
// RIGHT — catch errors and pass them to done
test('reads file', (done) => {
fs.readFile('/tmp/data.txt', 'utf8', (err, data) => {
if (err) return done(err);
expect(data).toContain('test');
done();
});
});
4. Use Jest's timer mocks for flaky timeouts
jest.useFakeTimers();
test('debounced search', async () => {
const search = jest.fn();
debouncedSearch('hello', search);
jest.advanceTimersByTime(300);
expect(search).toHaveBeenCalledWith('hello');
});
Expected output:
PASS tests/async.test.js
✓ fetches user data (45 ms)
✓ processes large dataset (12034 ms)
✓ reads file (8 ms)
Prevention Tips
- Always return promises from non-async tests
- Use
async/awaitinstead of raw.then()chains - Set
jest.setTimeout()injest.setup.jsfor slow CI environments - Use fake timers for setTimeout/setInterval-heavy code
- Add
--detectOpenHandlesto find unresolved promises
Common Mistakes with async test timeout
- Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
- Using
headandtailinstead of pattern matching, causing runtime errors on empty lists - Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
These mistakes appear frequently in real-world JEST code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro