Code that uses setTimeout() or setInterval() is hard to test quickly — waiting for real timers makes your suite slow. This lesson covers Jest's fake timers, which let you fast-forward time instantly and deterministically.
Enabling Fake Timers
jest.useFakeTimers() replaces the global timer functions (setTimeout, setInterval, Date, etc.) with controllable fake versions. Time doesn't pass automatically anymore — you advance it explicitly using functions like jest.advanceTimersByTime().
This means a test for code that waits 10 seconds can run in milliseconds, since Jest simulates the passage of time instead of actually waiting.
jest.useFakeTimers();
test('calls the callback after 1 second', () => {
const callback = jest.fn();
setTimeout(callback, 1000);
expect(callback).not.toHaveBeenCalled();
jest.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalledTimes(1);
});
No real second passes; jest.advanceTimersByTime(1000) simulates it instantly.
Fake Timer API
jest.useFakeTimers(); // enable fake timers
jest.advanceTimersByTime(ms); // fast-forward by a specific duration
jest.runAllTimers(); // run every pending timer to completion
jest.runOnlyPendingTimers(); // run only currently-queued timers (safer with intervals)
jest.useRealTimers(); // restore real timers
jest.advanceTimersByTime(ms) simulates exactly ms milliseconds passing.
jest.runAllTimers() runs every timer repeatedly until none remain — risky with setInterval (can loop forever).
jest.runOnlyPendingTimers() runs only timers already queued, safer for intervals.
Always call jest.useRealTimers() afterward (commonly in afterEach()) to avoid leaking fake timers into other tests.
Fake Timers Cheat Sheet
Every fake timer function you'll commonly use.
Function
Effect
jest.useFakeTimers()
Enables fake timers for the current test file
jest.advanceTimersByTime(ms)
Simulates ms milliseconds passing
jest.advanceTimersByTimeAsync(ms)
Same, but awaits any triggered microtasks
jest.runAllTimers()
Runs every pending and newly-created timer
jest.runOnlyPendingTimers()
Runs only currently-queued timers, once
jest.clearAllTimers()
Cancels all pending fake timers
jest.useRealTimers()
Restores real setTimeout/setInterval
Testing Debounce and Throttle Functions
Debounce and throttle utilities are classic fake timer use cases: you need to verify a function is delayed, cancelled, or rate-limited correctly, which is nearly impossible to test reliably with real timers due to timing flakiness.
test('debounce delays execution until the wait time passes', () => {
jest.useFakeTimers();
const fn = jest.fn();
const debounced = debounce(fn, 300);
debounced();
expect(fn).not.toHaveBeenCalled();
jest.advanceTimersByTime(299);
expect(fn).not.toHaveBeenCalled();
jest.advanceTimersByTime(1);
expect(fn).toHaveBeenCalledTimes(1);
});
Testing setInterval Safely
setInterval timers repeat indefinitely, so jest.runAllTimers() can loop forever if the interval is never cleared. Use jest.advanceTimersByTime() with a specific duration, or jest.runOnlyPendingTimers(), to safely test interval-based code.
afterEach(() => {
jest.clearAllTimers();
jest.useRealTimers();
});
test('polls every 5 seconds, 3 times in 15 seconds', () => {
jest.useFakeTimers();
const poll = jest.fn();
setInterval(poll, 5000);
jest.advanceTimersByTime(15000);
expect(poll).toHaveBeenCalledTimes(3);
});
Common Mistakes
Calling jest.runAllTimers() on code using setInterval, causing an infinite loop.
Forgetting to call jest.useRealTimers() after a test, leaking fake timers into later tests.
Not enabling fake timers before the code under test schedules its setTimeout/setInterval call.
Mixing real async waits (await new Promise(r => setTimeout(r, 100))) with fake timers in the same test.
Key Takeaways
jest.useFakeTimers() replaces real timers with controllable fake ones.
jest.advanceTimersByTime() simulates time passing instantly and deterministically.
Prefer jest.runOnlyPendingTimers() over jest.runAllTimers() for interval-based code.
Always restore real timers with jest.useRealTimers() after tests that enable fake ones.
Pro Tip
Add jest.useFakeTimers() in a beforeEach() and jest.useRealTimers() in an afterEach() for any test file that touches timers — it keeps timer state from leaking between tests without remembering to do it in every single test.
You now know how to control time in your tests. Next, explore snapshot testing for capturing and comparing serialized output.