javascriptjestjs

How to mock a constructor like new Date()


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()?


Solution

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