Setting Fake Times Natively in Jest

Published: Sun Feb 20 2022

TIL: Since v26 of Jest (which has been out for some time now), we've been able to fake/mock times natively in tests with jest.useFakeTimers function, including mocking the Date object. In my case, I needed to set a specific date and time for some components and then modify the time on a per-test basis to verify proper behvaiour.

Overview

To set current time in Jest to a specific time, call

// example
// setSystemTime accepts any Date object or Unix timestamp
jest.useFakeTimers().setSystemTime(new Date('2022-02-20'))

The result is that calling Date.now() in our tests will return the that we set the system time to:

new Date().getTime() // 2022-02-20 00:00:00

Setting fake times globally or by test

Calling useFakeTimers function at the file level with set it globally for all tests. A fake time can be set for a specific test-suite like so:

beforeEach(() => {
  jest.useFakeTimers().setSystemTime(new Date('2022-02-20'))
})

// clean up
afterEach(() => {
  // run any pending timers in your tests, e.g. setTimeout calls
  jest.runOnlyPendingTimers()
  // ready to switch back to real timers, inc. Date
  jest.useRealTimers()
})

Using fake time in tests

Once the fake time has been set, any calls to Date.now() will return the fake time. If we need to customise the return value of Date.now() in one of our tests to have it return some new time relative to our fake time, we can do so the following way:

// set Date.now() calls withing the implementation
// to return a new time 1s ahead of our fake time
jest
  .spyOn(Date, 'now')
  .mockImplementation(() => +Date.now() + 1000)

And that's it!

Resources