100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Testing

Mocking Timers

Learn how to use Jest's fake timers to control setTimeout, setInterval, and Date deterministically instead of waiting on real wall-clock time in tests.

MockingIntermediate9 min readJul 10, 2026
Analogies

Why Fake Timers?

Code that relies on setTimeout, setInterval, or Date for delays, polling, or debouncing is painfully slow and flaky to test if you actually wait out real time — a 5-second debounce would make every test take 5 real seconds, and network-dependent polling could make tests non-deterministic. jest.useFakeTimers() swaps the global timer functions for controllable fakes, so calling setTimeout(fn, 5000) inside the code under test schedules the callback against a simulated clock the test can advance instantly and deterministically.

🏏

Cricket analogy: Fast-forwarding through a rain delay instead of waiting out the real hours mirrors jest.useFakeTimers() letting a test skip real wall-clock waiting for a setTimeout-based delay.

Advancing Time

Once fake timers are active, jest.advanceTimersByTime(ms) simulates the passage of a given duration and synchronously fires any timers that would have fired within that window, which is the standard way to test a specific setTimeout callback. jest.runAllTimers() exhausts every pending timer including ones scheduled by other timers, which is convenient but dangerous for setInterval-based code since each fire can reschedule another timer and loop forever; jest.runOnlyPendingTimers() is the safer choice there, running only the timers currently queued without chasing newly scheduled ones.

🏏

Cricket analogy: A commentator jumping straight to 'over 40' on a highlights reel instead of watching every ball live mirrors jest.advanceTimersByTime() skipping straight to a point in simulated time.

javascript
beforeEach(() => {
  jest.useFakeTimers();
});

afterEach(() => {
  jest.useRealTimers();
});

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);
});

Modern vs Legacy Fake Timers

Since Jest 27, jest.useFakeTimers() defaults to the 'modern' implementation built on @sinonjs/fake-timers, which mocks not just setTimeout/setInterval but also Date, performance.now, and process.hrtime, giving full determinism to any code that reads the current time directly. If you need the older, timer-only behavior (for compatibility with a library that patches globals in a way modern fake timers conflict with), you can opt into jest.useFakeTimers('legacy') or configure legacyFakeTimers: true globally.

🏏

Cricket analogy: Switching from a stadium's analog clock to the broadcast's digital match clock, which can be synced precisely, mirrors modern fake timers also mocking Date for consistent time control.

Since Jest 27, jest.useFakeTimers() defaults to 'modern' fake timers (built on @sinonjs/fake-timers), which also mock Date, process.hrtime, and performance.now — pass { legacyFakeTimers: true } in config or jest.useFakeTimers('legacy') if you need the old behavior.

Combining Fake Timers with Async Code

Fake timers alone don't automatically flush pending Promise microtasks, so code that awaits a delay wrapped in setTimeout inside an async function needs jest.advanceTimersByTimeAsync(ms) (or wrapping advanceTimersByTime in an await with a manual microtask flush) so both the timer and the resulting Promise resolution happen before assertions run. Because fake timers globally replace the timer APIs for the whole process, it's essential to call jest.useRealTimers() in an afterEach once a test is done, or the fake clock can persist and silently affect other tests.

🏏

Cricket analogy: Forgetting to restart the real stadium clock after simulating a rain delay for one broadcast segment can throw off timing for the next match, mirroring forgetting useRealTimers() and leaking fake time into later tests.

If you call jest.useFakeTimers() in a test file but forget jest.useRealTimers() in an afterEach, the fake clock can silently persist into unrelated test files run in the same worker, causing confusing failures far from the actual cause.

  • jest.useFakeTimers() replaces setTimeout, setInterval, and related APIs with controllable fakes so tests don't wait on real wall-clock time.
  • jest.advanceTimersByTime(ms) simulates the passage of a specific duration, firing any timers scheduled within that window.
  • jest.runAllTimers() exhausts every pending timer, including ones scheduled by other timers, which can loop forever for repeating intervals.
  • jest.runOnlyPendingTimers() runs only the timers currently queued, safely handling setInterval without an infinite loop.
  • Since Jest 27, 'modern' fake timers are the default and also mock Date, performance.now, and process.hrtime for full determinism.
  • advanceTimersByTimeAsync (and its siblings) let fake timers cooperate with pending microtasks/Promises in async test code.
  • Always pair jest.useFakeTimers() with jest.useRealTimers() in afterEach to prevent fake time from leaking into unrelated tests.

Practice what you learned

Was this page helpful?

Topics covered

#Testing#JestStudyNotes#TestingQA#MockingTimers#Mocking#Timers#Fake#Advancing#StudyNotes#SkillVeris