Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jest typescript - Mock Date constructor

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?

like image 564
Ella Sharakanski Avatar asked Mar 29 '20 08:03

Ella Sharakanski


People also ask

How do you mock a constructor like a new date?

To mock a constructor like new Date() with Jest and JavaScript, we can use the setSystemTime method. beforeAll(() => { jest. useFakeTimers("modern"); jest. setSystemTime(new Date(2022, 3, 1)); }); afterAll(() => { jest.

How do you mock a date with Jest?

Mock the whole Date class with a fixed date instance Date = class extends Date { constructor(date) { if (date) { return super(date); } return currentDate; } }; expect(getCurrentDate()). toEqual(new Date('2019-05-14T11:01:58.135Z')); // Cleanup global. Date = realDate; });

How do you mock a constructor in Jest?

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.

How do you mock the current date in Jasmine?

it("should return decremented duration as time passes", () => { const timer = new Timer(5, true); jasmine. clock(). mockDate(new Date(startingTime + 1000)); expect(timer.


Video Answer


5 Answers

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!

like image 167
Riham Nour Avatar answered Nov 06 '22 15:11

Riham Nour


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.

like image 20
Yuci Avatar answered Nov 06 '22 14:11

Yuci


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();
like image 33
Malt Avatar answered Nov 06 '22 15:11

Malt


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
like image 26
Aaron Goldman Avatar answered Nov 06 '22 15:11

Aaron Goldman


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);
like image 39
widi83 Avatar answered Nov 06 '22 16:11

widi83