Never wait for real time in a test. Instead, control time with fake timers, or inject the clock.
Fake timers in Jest:
jest.useFakeTimers()replacessetTimeout,setInterval,Dateand related APIs with fake versions.jest.setSystemTime(new Date('2026-01-01T00:00:00Z'))fixes the value ofDate.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()inafterEach.
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.
Read more