I have a method which depends on new Date
to create a date object and then manipulates it. I'm testing that the manipulation works as expected, so I need to compare the returned date with expected date. In order to do that I need to make sure that new Date
returns the same value in the test and in the method being tested. How can I do that?
Is there a way to actually mock the return value of a constructor function?
I could create a module that can be required with a function that provides a date object and can be mocked. But that seems like an unnecessary abstraction in my code.
an example function to be tested...
module.exports = { sameTimeTomorrow: function(){ var dt = new Date(); dt.setDate(dt + 1); return dt; } };
how do I mock the return value of new Date()
?
Mock Date object js const RealDate = Date; beforeEach(() => { global. Date. now = jest. fn(() => new Date('2019-04-22T10:20:30Z').
const getCurrentDate = () => new Date(); test('It should create new date', () => { jest . spyOn(global, 'Date') . mockImplementationOnce(() => new Date('2019-05-14T11:01:58.135Z')); expect(getCurrentDate()). toEqual(new Date('2019-05-14T11:01:58.135Z')); });
In order to mock a constructor function, the module factory must return a constructor function. In other words, the module factory must be a function that returns a function - a higher-order function (HOF). Since calls to jest. mock() are hoisted to the top of the file, Jest prevents access to out-of-scope variables.
Use new Date() to get a Date for the current time or Date. now() to get the current time in milliseconds since 01 January, 1970 UTC. Returns a string representation of the current date and time.
Since jest 26, you can use the 'modern' fakeTimers implementation (see article here) wich supports the method jest.setSystemTime
.
beforeAll(() => { jest.useFakeTimers('modern'); jest.setSystemTime(new Date(2020, 3, 1)); }); afterAll(() => { jest.useRealTimers(); });
Note that 'modern'
will be the default implementation from jest version 27.
See documentation for setSystemTime
here.
Update: this answer is the approach for jest < version 26
see this answer for recent jest versions.
You can mock a constructor like new Date() using jest.spyOn
as below:
test('mocks a constructor like new Date()', () => { console.log('Normal: ', new Date().getTime()) const mockDate = new Date(1466424490000) const spy = jest .spyOn(global, 'Date') .mockImplementation(() => mockDate) console.log('Mocked: ', new Date().getTime()) spy.mockRestore() console.log('Restored: ', new Date().getTime()) })
And the output looks like:
Normal: 1566424897579 Mocked: 1466424490000 Restored: 1566424897608
See the reference project on GitHub.
Note: If you are using TypeScript and you would encounter a compilation error, Argument of type '() => Date' is not assignable to parameter of type '() => string'. Type 'Date' is not assignable to type 'string'
. In this case, a workaround is to use the mockdate library, which can be used to change when "now" is. See this question for more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With