1

We are using jest for mocking. I have a function which will greet us based on the time that file looks like below:

export default function getGreetingMessage() {
  const today = new Date();
  const curHr = today.getHours();

  if (curHr < 12) {
      return 'Good morning';
  } else if (curHr < 18) {
      return 'Good afternoon';
  }
  return 'Good evening';
}

And My test file will look like below

import getGreetingMessage from '../messages';

describe('messages', () => {
 function setup(date) {
  const DATE_TO_USE = new Date(date);
  global.Date = jest.fn(() => DATE_TO_USE);
 }
 it('should return good afternoon when time is greater than 12', () => {
  setup('Tue Oct 16 2018 15:49:11');
  expect(getGreetingMessage()).toEqual('Good afternoon');
});

it('should return good morning when time is less than 12', () => {
  setup('Tue Oct 16 2018 10:49:11');
  expect(getGreetingMessage()).toEqual('Good morning');
});

it('should return good evening when time is greater than than 19', () => {
  setup('Tue Oct 16 2018 19:49:11');
  expect(getGreetingMessage()).toEqual('Good evening');
});
});

When I ran each test individually it's working fine. When I ran all at a time then tests are failing.

I tried resetting the jest function. But not working.

Are there any other ways to try?

Thanks in advance :)

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Maharjun M
  • 853
  • 4
  • 11
  • 24

1 Answers1

2

This is bad practice to assign a mock to a global because it cannot be cleaned up:

global.Date = jest.fn(() => DATE_TO_USE);

Unmocked Date won't be available on subsequent setup calls:

const DATE_TO_USE = new Date(date);

It's unnecessary to provide the implementation with jest.fn, it can be changed per test. Since it's Date object that is expected, original Date may be used to create instances:

const OriginalDate = Date;

beforeEach(() => {
  jest.spyOn(global, 'Date');
});

it('', () => {
  Date.mockImplementation(() => new OriginalDate('Tue Oct 16 2018 15:49:11'));
  expect(getGreetingMessage()).toEqual('Good afternoon');
});
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • `Date.mockReturnedValue` is throwing error. it's showing that Date.mockReturnedValue is not function. – Maharjun M Oct 16 '18 at 07:10
  • This was a typo. – Estus Flask Oct 16 '18 at 07:40
  • Does it really work? I am using the code above in TypeScript but got `Property 'mockReturnValue' does not exist on type 'DateConstructor'.ts(2339)` – choasia Feb 28 '19 at 02:41
  • @choasia The question doesn't involve TS, no wonder the code causes type problems as is. Try to assert a type, `(Date as jest.Mock).mockReturnValue(...)` – Estus Flask Feb 28 '19 at 10:27
  • @estus Thank you for your support, but I got `today.getHours() is not a function` subsequently. I debugged it with console.log and `today.getHours` seemed to be `undefined`... – choasia Feb 28 '19 at 11:05
  • It likely should be mockImplementation instead of mockReturnValue because it's a constructor. – Estus Flask Feb 28 '19 at 11:15
  • 1
    @estus Aha, it works now. Thank you so much. By the way, I decided to use `const dateToUse = new Date("Tue Oct 16 2018 11:49:11"); jest.spyOn(global, "Date").mockImplementation(() => dateToUse);` to avoid the type issue above. – choasia Feb 28 '19 at 14:01