jest typescript - Mock Date constructor

12,100

Solution 1

well I tried this solution, and it worked..

class MockDate extends Date {
    constructor() {
        super("2020-05-14T11:01:58.135Z"); // add whatever date you'll expect to get
    }
}

and in the beforeEach of that test, I added:

// @ts-ignore
global.Date = MockDate;

this way whenever I called a function that had new Date() inside, it would return the date I added in the constructor of the MockDate class above!

Solution 2

A workaround is to use the mockdate library, which can be used to change when "now" is.

const MockDate = require('mockdate');

test('Mock Date to change when "now" is', () => {
  console.log('Normal:   ', new Date().getTime());

  MockDate.set(new Date(1466424490000));

  console.log('Mocked:   ', new Date().getTime());

  MockDate.reset();

  console.log('Restored: ', new Date().getTime());
});

And the test result is like:

$ npm run test
> jest

 PASS  src/test.ts
  ✓ Mock Date to change when "now" is (8ms)

  console.log src/test.ts:4
    Normal:    1585505136315

  console.log src/test.ts:8
    Mocked:    1466424490000

  console.log src/test.ts:12
    Restored:  1585505136322

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.804s

See the reference project on GitHub.

Solution 3

Just tell the compiler what it wants to hear: say its a string with cast to unknown followed by the cast to string:

const now = new Date() as unknown as string

Solution 4

Daryn's inference comment on Arron's answer works great with no extra packages.

const mockDate = new Date();
jest.spyOn(global, "Date").mockImplementation(() => (mockDate as unknown) as string);
const myDate = new Date();

Solution 5

I have the same issue when mocking a new Date() using jest typescript when try to mocking Date inside a function :

export const checkValidTime(): boolean => { 
  const now = new Date();
  const maxAllowTime = new Date('2020-02-02 09:00:00');

  console.log(`currentTime: ${now.toLocaleString()}`);
  console.log(`maxAllowTime: ${maxAllowTime.toLocaleString()}`);

  return now > maxAllowTime;
}

Mocking solution in unit test:

const mockDate = new Date('2021-09-03 08:00:10');
jest
    .spyOn(global, 'Date')
    .mockImplementationOnce(() => (mockDate as unknown) as string);
const valid = checkDateTime();
expect(valid).toEqual(true);
Share:
12,100
Ella Sharakanski
Author by

Ella Sharakanski

I have 7 years of experience as a software developer. For the past two years, I have been working at a startup called Salto, developing features end-to-end (including backend, frontend, DB design, API design). Before that, I served in the IDF for 5 years as a software developer and then as a full-stack team leader. I'm good at Python, TypeScript, JavaScript, React, Node.js, REST API, GraphQL, MySQL, and PostgreSQL. I also have experience with Django, C#, and Entity Framework. Aside from that, I have a Bachelor's degree in applied mathematics and a Master's degree in computer science, including a thesis about high-dimensional expander graphs. I love solving problems, and most of all, I love creating products that bring high value to customers.

Updated on June 06, 2022

Comments

  • Ella Sharakanski
    Ella Sharakanski about 2 years

    I'm trying to mock new Date() to return a specific date. The following code:

    const now = new Date()
    jest.spyOn(global, 'Date').mockImplementation(() => now)
    

    gives a compilation error: Argument of type '() => Date' is not assignable to parameter of type '() => string'. Type 'Date' is not assignable to type 'string'.

    I think the reason is that jest thinks I'm trying to mock Date() instead of new Date(). Indeed, Date() returns a string. How can I solve this issue?