Jest Fake Timers Not Advancing Fix
In this tutorial, you'll learn about Jest Fake Timers Not Advancing Fix. We cover key concepts, practical examples, and best practices.
Your setTimeout callback never runs during the test — even after calling jest.advanceTimersByTime(), the timer doesn't fire.
The Problem
// WRONG — fake timers enabled after the timer is already set
const callback = jest.fn();
setTimeout(callback, 1000);
jest.useFakeTimers();
jest.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled(); // FAILS
Expected number of calls: 1
Received number of calls: 0
The timer was created using real timers because jest.useFakeTimers() was called after setTimeout. Fake timers only affect timers created after they're enabled.
Step-by-Step Fix
1. Enable fake timers before timer creation
// RIGHT — enable fake timers first
jest.useFakeTimers();
const callback = jest.fn();
setTimeout(callback, 1000);
jest.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled();
2. Use jest.runAllTimers for immediate execution
// RIGHT — run all pending timers
jest.useFakeTimers();
const callback = jest.fn();
setInterval(callback, 500);
jest.runAllTimers();
expect(callback).toHaveBeenCalled();
3. Advance timers with granular control
// RIGHT — step through timers
jest.useFakeTimers();
const fn = jest.fn();
setTimeout(() => fn('step1'), 100);
setTimeout(() => fn('step2'), 200);
jest.advanceTimersByTime(150);
expect(fn).toHaveBeenCalledWith('step1');
expect(fn).not.toHaveBeenCalledWith('step2');
jest.advanceTimersByTime(50);
expect(fn).toHaveBeenCalledWith('step2');
4. Configure fake timers with modern API
// RIGHT — modern fake timers configuration
jest.useFakeTimers({
legacyFakeTimers: false,
advanceTimers: false,
});
const fn = jest.fn();
setTimeout(fn, 1000);
jest.advanceTimersByTime(1000);
expect(fn).toHaveBeenCalled();
Expected output:
PASS tests/timer.test.js
✓ advances timers (8 ms)
✓ runs all timers (3 ms)
✓ granular control (5 ms)
Prevention Tips
- Call
jest.useFakeTimers()at the top of tests or inbeforeEach - Use
jest.advanceTimersByTime()for precise timer control - Use
jest.runAllTimers()to execute all pending timers - Restore real timers with
jest.useRealTimers()inafterEach - Use
jest.clearAllTimers()to remove pending timers
Common Mistakes with mock timer
- 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
- Using
returnto exit a function early instead of wrapping a pure value in the monad
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