question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Spy on global date has very weird behaviors

See original GitHub issue

Hello, I have some test where I need to control what new Date returns, so I went through the way of spy on global.date. However, it is not honouring the implementation very well, and the behavior I’m getting is quite strange.

If I go with this simple implementation:

const mockDate = jest.spyOn(global, 'Date');
mockDate.mockImplementation(x => x );

What I get as output is just an empty object instead of the symbol I’m passing into it. For some reason, changing the implementation to something like this, makes it work (in some situations)

const mockDate = jest.spyOn(global, 'Date');
mockDate.mockImplementation(x => ({date: x}) );

Then, it returns {date: symbol('whatever')}, which I can use to check (although is a bit weird). Things start to get funny when such value is passed to another mock function, something equally simple:

const parse = {
  makeDate: jest.fn(x => x).mockName('makeDate'),
};

The code I’m testing calls this mock function like this:

 parse.makeDate(new Date(startDate))  // startDate is a Symbol on my tests

So later I have to do expect(parse.makeDate).toHaveBeenCalledWith({ date: startDate });. Is there any other way to have a more simplistic implementation of this?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
yacinehmitocommented, Dec 1, 2019

Hello 👋

In the first case, new Date() will give you an empty object because x => x is called as a constructor. When something is returned in a constructor, the behaviour in JavaScript is the following:

  1. if the value is a primitive, it is ignored
  2. if the value is an object, it is returned instead of the newly created object

So, when you just use the symbol, you end up in case 1. The symbol is ignored, so a new object is created and returned. It is empty because the constructor your are using is a simple function that does not mutate this (and has nothing in its prototype property).

When you use { date: symbol('whatever') }, the constructor now returns an object, which means that we are in case 2. You get back was is returned; it’s still not a Date.

Is there any other way to have a more simplistic implementation of this?

It depends on what your are trying to achieve, why you are using a symbol in the first place and how you want to make your assertion.

As far as I am concerned my experience with mocking Date has been pretty straightforward but the setup to make is pretty involved. I usually use the following code:

// Save the Date constructor for later use
const Date = global.Date;

// When calling `new Date()` in the code that is tested, it delegated to the actual `Date`
// This doesn't work at all when code calls only `Date()`
const mockDate = jest.fn((...args) => {
  return new Date(...args)
});

// This is to make `mockDate` look pretty close to the actual `Date`
mockDate.name = 'Date';
mockDate.prototype = Date.prototype;

// Mocking static functions as well
mockDate.now = jest.fn(Date.now);
mockDate.parse = jest.fn(Date.parse);
mockDate.UTC = jest.fn(Date.UTC);

// `mockDate.mockReturnValue` doesn't seem to work when `Date` is called as a constructor
// This is a little hack that also has the benefit of checking that we return an actual `Date`
mockDate.mockReturnDate = (date) => {
  if (!(date instanceof Date)) {
    throw new TypeError('Value provided to mockDate is not a Date');
  }
  return mockDate.mockImplementation(() => date);
};

// Replaces `Date` by the mock
global.Date = mockDate;

I have no idea if this is the recommended way of mocking Date but I have had success with it.

0reactions
github-actions[bot]commented, May 3, 2022

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

9 Signs Someone Is Spying on Your Phone - CyberGhost VPN
You'll notice strange behavior, like high battery usage, an elevated temperature, and poor performance.
Read more >
How to mock a constructor like new Date() - Stack Overflow
I'm testing that the manipulation works as expected, so I need to compare the returned date with expected date.
Read more >
The World-Changing Race to Develop the Quantum Computer
The world of subatomic particles is the quantum scale. It is the world of strange effects: interference and uncertainty and entanglement.
Read more >
Pokémon Scarlet and Violet: How Pokémon react to weather ...
As Sandygast is a Ghost/Ground-type Pokémon, it too is weak to water. Both Sudowoodo and Sandygast show behaviors on the field that reflect ......
Read more >
How TikTok Reads Your Mind | Legacy Marketing
It's no secret that TikTok has become one of the most popular social media platforms in the world, with over 1 billion monthly...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found