Jest: Jest mock/spy returns undefined even when set up

Created on 4 Nov 2019  路  12Comments  路  Source: facebook/jest

馃悰 Bug Report

Mocking spy return does nothing

I'm about to lose my mind here; it seems the entire mock system is b0rked. I copy-paste the examples from the docs, and they don't work.

To Reproduce

// __mocks__/someUtil.js
export default {
  m1: jest.fn(() => 42),
}
// someUtil.test.js
import someUtil from './someUtil';

jest.mock('./someUtil')

console.log(someUtil.m1) // expected spy stuff
console.log(someUtil.m1()) // undefined 馃く


Other variations that also do nothing

// __mocks__/someUtil.js

throw; // does throw

export default {
  m1: jest.fn(() => throw), // does NOT throw
}

// ---

export default {
  m1: jest.fn().mockImplementation(() => 42),
}

// ---

export default {
  m1: jest.fn().mockImplementation(() => throw), // does NOT throw
}

// ---

export default {
  m1: jest.fn().mockReturnValue(42),
}

// ---

export default () => ({
  m1: jest.fn().mockImplementation(() => 42),
})

// ---

export default () => ({
  m1: jest.fn().mockReturnValue(42),
})

Expected behavior

As documented: it should return 42

envinfo

jest version: 24.7.1

Bug Report Needs Repro Needs Triage

Most helpful comment

A little late here, but I was just having this exact issue. I discovered that someone had added resetMocks: true to the jest.config.js file. This means that the _implementations_ of mock functions are reset before each test. So in our case, the mock function was being included in the mocked module at test runtime, but that mock had been reset, so it returned undefined.

Regarding the original issue build environment, it looks like react-scripts does indeed add resetMocks: true into the jest config. (https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/scripts/utils/createJestConfig.js#L69) But you can override it on the jest key of your package.json. (https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/scripts/utils/createJestConfig.js#L74)

All 12 comments

I think you need to check something in your config, because everything is Ok.
You can check here your exemple:
https://repl.it/repls/GrossDapperLinuxkernel

  • Need you import from import someUtil from './__mocks__/someUtil' ?

@joelbarbosa thanks for chiming it. The example you provided doesn't appear to actually be mocking anything: the actual implementation is itself just a mock:

// someUtil.js
module.exports = {m1: jest.fn(() => 42)}

Not sure if that matters, but I would guess it does.

Also not quite apples-to-apples: module.exports vs export default

As I understand it, you are not meant to import the mock: jest.mock handles that.

Yes it's mocking, you can check in the imagens:
image
image
image

I saw that it is logging a mock. I _think_ it's not the same because jest.mock('someUtil) is not actually doing anything: the real implementation is itself a spy.

My project's jest configuration is coming from react-scripts. The only thing I've done is a setupConfig where I globally add the enzyme adapter for react 16.

Yes, I think jest.mock('someUtil) is working, jest is isolating it you can check more example here:
https://medium.com/@rickhanlonii/understanding-jest-mocks-f0046c68e53c

In your repl example, if I remove the jest.mock(), the test behaves exactly the same with exactly the same output, so it's definitely not doing anything.

Oh yeah, of course it is doing.
when you add jest.mock('./someUtil') you are reassign all the exported functions to the mock.

as you can see, I'll change the behavior of my function.


jest.mock('./someUtil', () => ({
  m1: jest.fn(() => 'mock me again')
}));

console.log(someUtil.m1); // [Function: mockConstructor].....
console.log(someUtil.m1()); // mock me again

I created a representative example (https://repl.it/repls/GaseousAcrobaticMainframe), but it does not behave the same locally: Locally, calling the mocked getItem() in the actual implementation returns undefined, but calling it in the test returns the expected Promise { { id: '29ed6982-3959-450e-b3cf-bf82b2fa14b1' } }. When I log getItem (without calling it), it returns a mock object in both the implementation and the test.

I'm using the same version of Jest (24.9.0). The only difference I can think of is my local was generated from create-react-app, so the Jest configuration comes from that.

@jacob-fueled have you fixed this issue?

@mateuszs Yes: I stopped using Jest. I could not figure out what the problem was; it quite possibly was coming from create-react-app, but I'd already sank far too many hours trying to get an out-of-the-box feature to work :(

A little late here, but I was just having this exact issue. I discovered that someone had added resetMocks: true to the jest.config.js file. This means that the _implementations_ of mock functions are reset before each test. So in our case, the mock function was being included in the mocked module at test runtime, but that mock had been reset, so it returned undefined.

Regarding the original issue build environment, it looks like react-scripts does indeed add resetMocks: true into the jest config. (https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/scripts/utils/createJestConfig.js#L69) But you can override it on the jest key of your package.json. (https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/scripts/utils/createJestConfig.js#L74)

resetMocks: true was the culprite for me too.

mock implementations can work with resetMocks: true if you setup the mocks in beforeEach, or directly inside the test/it callbacks.

If you set up the mocks at the top level of the module, in the describe callback (but outside of any it/test callback), or in beforeAll, they get overwritten by resetMocks AFAICT

Was this page helpful?
0 / 5 - 0 ratings