CodePark/ questions / Async code, timers & time
START PRACTICINGPRACTICE
Backend question · Backend testing › Async code, timers & time

How do you test code that depends on timers or the current time, such as a token that expires after 15 minutes or a retry with backoff?

Never wait for real time in a test. Instead, control time with fake timers, or inject the clock.

Fake timers in Jest:

  • jest.useFakeTimers() replaces setTimeout, setInterval, Date and related APIs with fake versions.
  • jest.setSystemTime(new Date('2026-01-01T00:00:00Z')) fixes the value of Date.now().
  • jest.advanceTimersByTime(15 * 60_000) moves the clock forward and fires the timers that are due.
  • When the code awaits promises between timers, use await jest.advanceTimersByTimeAsync(ms). It lets promise callbacks run between steps.
  • Restore real timers with jest.useRealTimers() in afterEach.

Vitest has the same API on vi.

Inject the clock: this is often cleaner. Pass in a clock (now(): Date) or pass now as an argument. Then your expiry logic becomes a pure function, and you test it with fixed dates.

Use UTC and fixed dates, never "today". This avoids surprises from time zones and DST (daylight saving time).

  • Never use real sleeps in tests.
  • Fake timers use useFakeTimers, setSystemTime and advanceTimersByTime.
  • Use the async advance variant when promises sit between timers.
  • Injecting a clock turns time logic into a pure function.
  • Fixed UTC dates avoid flaky tests caused by time zones.