richwol
richwol

Reputation: 1165

Jest.fn - return value returns undefined when using jest.mock

I have the following file I'm trying to write unit tests for:

import { document } from '../../globals';
const Overlay = () => {
  console.log(document.getElementsByTagName()); // this outputs 'undefined'
};

I'm struggling to mock the getElementsByTagName function. My test looks like this.

import { document } from '../../globals';
jest.mock('../../globals', () => ({
  document: {
    getElementsByTagName: jest.fn().mockReturnValue('foo')
  }
}));
console.log(document.getElementsByTagName()); // this outputs 'foo'

But unfortunately, the console.log in the top file always outputs undefined. It can see the document object and the getElementsByTagName mock, but the return value is always undefined.

If I console.log(document.getElementsByTagName) I get the following:

{ getElementsByTagName:
   { [Function: mockConstructor]
     _isMockFunction: true,
     getMockImplementation: [Function],
     mock: [Getter/Setter],
     mockClear: [Function],
     mockReset: [Function],
     mockReturnValueOnce: [Function],
     mockReturnValue: [Function],
     mockImplementationOnce: [Function],
     mockImplementation: [Function],
     mockReturnThis: [Function],
     mockRestore: [Function] },
}

But if I do the same in the other file I get this:

function () {
  return fn.apply(this, arguments);
}

My suspicion is that jest.mock is wrapping the jest.fn mock in another function.. any ideas?

Upvotes: 27

Views: 25041

Answers (2)

Daniel Long
Daniel Long

Reputation: 1647

In my case, I was using react-scripts to run tests. (Within my package.json the test attribute was set to react-scripts test).

Thankfully, I stumbled on this Stack Overflow answer, where I found that by default react-scripts will set jest.resetMocks to true. In a standard jest configuration, this is false.

This means when running with react-scripts test, before every test run, your mock implementation will be completely reset and your mock function will return undefined.

A couple ways to fix this:

  1. Within your package.json, add a resetMocks: false to your jest configuration:
"jest": {
  ...,
  "resetMocks": false
}
  1. Define your mock in a beforeEach function

Upvotes: 5

gfullam
gfullam

Reputation: 12045

Try using .mockReturnValue() after assignment

I encountered the same behavior and found success by calling mockFn.mockReturnValue(value) after assignment.

For example:

import { document } from '../../globals.js'

jest.mock('../../globals.js', () => ({
  document: {
    getElementsByTagName: jest.fn()
  }
}))

document.getElementsByTagName.mockReturnValue('foo')

console.log(document.getElementsByTagName()); // this outputs 'foo'

I have seen both patterns within the jest documentation.

I wonder if the latter case requires some other pattern of interaction to assert on the mocked return value, but I haven't figured it out. I can't seem to replicate success using the spyOn pattern suggested in another answer here.

Upvotes: 13

Related Questions