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
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