Mocking moment with Jest

Moment library comes in handy when an implementation requires complex operations based on dates. Although it is a bit heavy and tricky to mock, the library can be very useful. In this article, I describe how to mock the moment library for unit tests.

Mocking moment itself

Most of the functions offered by moment do not require to be mocked and it is hard to imagine a problem requiring mocking functions like add, subtract, or format. The variable and hard to predict part of the moment features is the current date and time. It can be mocked with the jest.mock function:

jest.mock("moment", () => {
    return () => jest.requireActual("moment")("11.02.2022 10:10", "DD.MM.YYYY HH:mm");
});

When the moment function is called, it returns a moment object initialized with a hardcoded date.

test("Return mocked date", () => {
    assert.equal(moment().format("DD.MM.YYYY HH:mm"), "11.02.2022 10:10");
});

A simple test case proves that the mock works correctly. However, it fails if it initializes the moment function with any date or object:

test("Initialized moment object returns correct time", () => {
    const testDate = moment("11.02.2022 15:10", "DD.MM.YYYY HH:mm")
    assert.equal(testDate.format("HH:mm"), "15:10");
});

In the example above, all moment overloads are mocked with one function , which doesn’t cover all use cases. The best idea is to mock only one overload, which returns the current date and time. All the other implementations can stay in their original version. It’s covered with one conditional statement in the snippet below:

jest.mock("moment", () => {
    return (...args: any[]) => {
        if (args.length > 0) {
            return jest.requireActual("moment")(...args);
        }
        return jest.requireActual("moment")("11.02.2022 10:10", "DD.MM.YYYY HH:mm");
    }
});

This mock works perfectly with both examples presented in the article and ensures the correct execution of all other functions available in the moment library.

Mocking Date.now

The alternative solution is to mock Date.now function. It is used by the moment library to get the current date and time.

jest.spyOn(Date, "now").mockImplementation(() => {
    return new Date(2022, 1, 11, 10, 10, 0).getTime();
    //return new Date("2022-02-11T09:10:00.000Z").getTime();
});

I personally prefer the second option, because it covers usage of both: moment and Date and it takes only three lines of code without a conditional statement.