Skip to content Skip to sidebar Skip to footer

Mocking Moment() And Moment().format Using Jest

I'm unable to mock moment() or moment().format functions. I have states where, currentDateMoment and currentDateFormatted are getting set as below. currentDateMoment: moment() //20

Solution 1:

The easiest way to mock moment() and any function that it uses (i.e. .day(), .format()) is to change the Date that moment() uses under the hood

Add the snippet below inside your test file

Date.now = jest.fn(() => new Date("2020-05-13T12:33:37.000Z"));

This makes it so anytime moment() is called in your tests, moment() thinks that today is Wednesday, May 13th 2020

Solution 2:

You can mock Moment to return a specific date, then format don't have to be mocked.

jest.mock('moment', () => {
  return() => jest.requireActual('moment')('2020-01-01T00:00:00.000Z');
});

By doing so, any call to Moment() will always return a moment object with date set to 2020-01-01 00:00:00

Here is an example with a function that return the date of tomorrow and the test for this function.

const moment = require('moment');
consttomorrow = () => {
  const now = moment();
  return now.add(1, 'days');
};

describe('tomorrow', () => {
  it('should return the next day in a specific format', () => {
    const date = tomorrow().format('YYYY-MM-DD');
    expect(date).toEqual('2020-01-02');
  });
});

Solution 3:

Here is the solution:

index.ts:

import moment from'moment';

exportfunctionmain() {
  return {
    currentDateMoment: moment().format(),
    currentDateFormatted: moment()
      .format('MM-DD-YYYY')
      .valueOf()
  };
}

index.spec.ts:

import { main } from'./';
import moment from'moment';

jest.mock('moment', () => {
  const mMoment = {
    format: jest.fn().mockReturnThis(),
    valueOf: jest.fn()
  };
  return jest.fn(() => mMoment);
});

describe('main', () => {
  test('should mock moment() and moment().format() correctly ', () => {
    (moment().formatas jest.MockedFunction<any>)
      .mockReturnValueOnce('2018–01–30T12:34:56+00:00')
      .mockReturnValueOnce('01–30-2018');
    expect(jest.isMockFunction(moment)).toBeTruthy();
    expect(jest.isMockFunction(moment().format)).toBeTruthy();
    const actualValue = main();
    expect(actualValue).toEqual({ currentDateMoment: '2018–01–30T12:34:56+00:00', currentDateFormatted: '01–30-2018' });
  });
});

Unit test result with 100% coverage:

 PASS  src/stackoverflow/55838798/index.spec.ts
  main
    ✓ should mock moment() and moment().format() correctly  (7ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.795s, estimated 8s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/55838798

Solution 4:

mockdate works for me

import mockDate from"mockdate";


test('Should add some', () => {
    mockDate.set(newDate('2/20/2020'));

    const action = addSome();

    expect(action).toEqual({
        createdAt: moment()
    });

    mockDate.reset();
})

Solution 5:

The other answers tell you how to mock moment, but you don't need to mock moment to test that code. You probably shouldn't, in fact; it's a complicated third party interface you don't own and mocking it couples your tests to it, you end up testing implementation rather than behaviour.

Rather than calling moment() without any arguments, call it with the current date (per https://momentjscom.readthedocs.io/en/latest/moment/01-parsing/01-now/moment() is basically moment(new Date())). Then that current date comes from a function you do own:

const { getCurrentDate } = require('path/to/utils');

exportconstcreateSomething =() => ({
  currentDateMoment: moment(getCurrentDate()),
  currentDateFormatted: moment(getCurrentDate()).format('MM-DD-YYYY'),
});

so you can trivially mock that out in the tests:

const { createSomething } = require('path/to/impl');
const { getCurrentDate } = require('path/to/utils');
jest.mock('path/to/utils');

it('formats the data correctly', () => {
  getCurrentDate.mockReturnValue(newDate(2021, 3, 29));

  const { currentDateFormatted } = createSomething();
  expect(currentDateFormatted).toEqual('2021-04-29');
});

Now the test doesn't refer to moment, which has become an implementation detail, at all. If there's a breaking future change to the moment API you'll find out about it, because your tests will fail; they'd misleadingly pass if it was mocked. If you want to switch to a different library you can do so, confident that the tests mean the behaviour is still correct (here's an example doing the same thing with DayJS).

Post a Comment for "Mocking Moment() And Moment().format Using Jest"