I\'m unable to mock moment()
or moment().format
functions. I have states where, currentDateMoment
and currentDateFormatted
ar
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');
const tomorrow = () => {
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');
});
});
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
mockdate works for me
import mockDate from "mockdate";
test('Should add some', () => {
mockDate.set(new Date('2/20/2020'));
const action = addSome();
expect(action).toEqual({
createdAt: moment()
});
mockDate.reset();
})
Here is the solution:
index.ts
:
import moment from 'moment';
export function main() {
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().format as 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
To Mock Moment().format()
,startOf()
, isValid()
or isAfter()
etc. Can refer below example.
jest.mock('moment', () => {
const momentParams = {
format: jest.fn(() => '10/04/2020'),
startOf: jest.fn().mockReturnThis(),
isAfter: jest.fn().mockReturnValue(true),
isValid: jest.fn().mockReturnValue(true)
};
const fn = jest.fn(newMoment => {
momentParams.format = jest.fn(() => newMoment);
return momentParams;
});
return fn;
});
And last you can write a test case like this. eg.
test('should returned mocked value for isAfter()', async () => {
jest.spyOn(moment(), 'isAfter').mockReturnValue(false);
const response = moment().isAfter();
expect(response).toBe(false)
})
Don't use import * as moment from 'moment';
Use the default import
import moment from 'moment';
// tsconfig.json
{
"compilerOptions": {
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
}
}
read