Jest setSystemTime not working with global scope

Viewed 9119

I am trying to tests a simple reducer which has a date property set to today.

const today = new Date();

export const initialState = {
  today
};

console.log(new Date().toDateString()); // <--- real date

export default function globalReducer(state = initialState, action) {
  console.log(new Date().toDateString()); // <--- mocked date
  switch (action.type) {
    default:
      return state;
  }
}

with my basic test

import globalReducer from "./reducer";

describe("Global reducer", () => {
  beforeAll(() => {
    jest.useFakeTimers("modern");
    jest.setSystemTime(new Date("2021-02-18"));
  });

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

  it("should return the mocked date", () => {
    expect(globalReducer(undefined, {}).today).toEqual(new Date('2021-02-18'));
  });
});

What I noticed is that the mock only works inside the reducer code, but today in its global scope always returns the real date instead of the mocked one.

If I call the setSystemTime in the test setup file, then today is correctly mocked.

Am I missing something here? What would be the way of mocking a date in global scope only for a specific test?

A test repo is here if you want to check it out https://github.com/dariospadoni/jestFakeTimersMock

2 Answers

The reason for it to happen is because the Date is instantiated in recucer.js before setSystemTime is invoked.

Here is an example how you can avoid that:

beforeAll(() => {
  jest.setSystemTime(new Date("2021-02-18"));
});

describe("Global reducer", () => {
  let globalReducer;

  beforeAll(() => {
    globalReducer = require("./reducer").default;
  });

  it("should return the mocked date", () => {
    expect(globalReducer(undefined, {}).today).toEqual(new Date("2021-02-18"));
  });
});

Here the Date object will be instantiated once the reducer.js is required, and that would be after the setSystemTime is invoked

In my case, it's not working inside fakeAsync function. I kept seeing the real date when i console log. Removing the test from fakeAsync and I can see the mocked date.

Related