Closed jacob-fueled closed 3 weeks ago
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
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:
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
@dstapleton92 Thank you so much, I sank a ton of time into google trying to find this answer!
In my case I wanted to mock a value that got evaluated upon loading the file:
export const store = createStore(...);
This was always returning undefined, no resetMocks
setting.
Instead I had to do:
export const store = () => {
return createStore(...);
}
@dstapleton92 thank you! I've spent hours on this.
Could we have something on this somewhere in the documentation ?
@dstapleton92 - thank you again! I've spent half a day on this and I'm glad I targetted for CRA as the culprit and not Jest!
Spent one day until I landed here and figured out that CRA is causing mocks to be reset by default. That should definitely not be a default behaviour.
This also caught me totally by surprise. We've been using restoreMocks
in our jest.config.js
to ensure all mocked spies are reverted to their original implementation between tests.
But I would have never have expected the restoration of mock functions to restore their original implementations to affect mock functions created on-the-fly with jest.fn()
as well. Is there actually a use-case for resetting jest.fn(() => 42)
to jest.fn()
??
I know (now) it's documented:
And it's probably consistent as both jest.fn(() => 42)
and jest.spyOn(obj, 'method').mockReturnValue(42)
add mock implementations. But I'm sure it will keep tripping people up.
For me it was jest.resetAllMocks();
!
I have been having the same issue. The examples do not work. I get errors of "cannot call .then of undefined". I too am using react-scripts.
putting "resetMocks": false into the "jest" portion of my package.json file fixed the problem immediately.
I've been pulling my hair out over this for 2 days! I agree that this "attribute" should be more widely published.
Perhaps, the jest.fn and jest.mock() documentation can mention that if the mocks get reset then the mocks set up in the top of the test file will no longer work. Lots of people create apps via react scripts and this has to be happening to lots more people.
Just lost a heap of hours on this also. I really feel like resetMocks: true
shouldn't apply to global mock implementations.
Had a similar issue where I couldn't figure out why the import I was trying to mock was ending up undefined
. I was trying
const mockMyImport = jest.fn()
jest.mock('my-module', () => ({
...jest.requireActual('my-module'),
myImport: mockMyImport,
}));
describe(`MyComponent test`, () => {
it('works', async () => {
mockMyImport.mockImplementation(() => {
console.log("in mocked implementation")
return 42
})
const { toJSON } = render(<MyComponent />)
expect(toJSON()).toMatchSnapshot();
});
});
but in my component, logging myImport
would show that it was always undefined
. This, however, works:
import { myImport } from 'my-module'
jest.mock('my-module', () => ({
...jest.requireActual('my-module'),
myImport: jest.fn(),
}));
describe(`MyComponent test`, () => {
it('works', async () => {
(myImport as jest.Mock).mockImplementation(() => {
console.log("in mocked implementation")
return 42
})
const { toJSON } = render(<MyComponent />)
expect(toJSON()).toMatchSnapshot();
});
});
So in other words, you have to access the mocked import by actually importing it in the test rather than using the variable that you assigned the import to be mocked by....
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 thetest
/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
@HenryCharlesAnderson thanks for providing this information. I tried putting jest.mock(...)
inside the it
callback function and it's still not working. I tried putting it under beforeEach()
function and that didn't work either. The only way I could get it working is to set resetMocks
to false in package.json. Any ideas why this is the case?
Here's some sample code I've written to test this for more context. In this example, jest.resetMocks
in package.json is set to false and it works. The moment I set it to true, this fails. As mentioned above, moving jest.mock()
block into the callback function ofit()
and beforeEach()
functions do not work.
// simplefn.ts
const simplefn = (message: string): string => message;
export default simplefn;
// simplefn.test.ts
import simplefn from '../simplefn';
jest.mock('../simplefn', () => ({
__esModule: true,
default: jest.fn((msg) => 'hello'),
}));
beforeEach(() => {
jest.restoreAllMocks(); // Contrary to my expectation, this line does not cause jest.mock() to become reset
});
describe('test simplefn', () => {
it('works with jest.fn', () => {
const result = simplefn('test');
expect(result).toBe('hello');
expect(simplefn).toHaveBeenCalledTimes(1);
});
});
I had the same problem in my React project. Putting resetMocks: false
into package.json did not fix it. I know that jest.mock is not broken but I can't get the simple examples to work either. The weird thing is that when I use VSS interactive debugger, it shows the dummyPromise
implementation is my mocked implementation, but there is no evidence of mocked function support. _isMockFunction
is undefined.
I have found that I can implement the supposed jest.mock behavior by using jest.spyon, mockImplementation, and importing from mocks directory.
import {dummyPromise} from '../services/DummyService';
jest.mock('../services/DummyService');
describe('grasping at straws why mocking service promises is not working', ()=>{
beforeEach(()=>{
//jest.mock('../services/DummyService.js'); // still does not work
})
test('can get a mock', ()=>{
//jest.mock('../services/DummyService.js'); // still does not work
expect(jest.isMockFunction(dummyPromise)).toBeTruthy();
})
})
As you can see, putting the jest.mock()
into beforeEach or in the test has no change in behavior.
/* eslint-disable jest/no-mocks-import */
import * as DummyService from '../services/DummyService';
import * as DummyServiceMocks from '../services/__mocks__/DummyService';
const mockDummyPromise = jest.spyOn(DummyService, 'dummyPromise');
mockDummyPromise.mockImplementation(DummyServiceMocks.dummyPromise);
describe('grasping at straws why mocking service promises is not working', ()=>{
test('can get a mock', ()=>{
expect(jest.isMockFunction(mockDummyPromise)).toBeTruthy();
})
test('can call the mock', async ()=>{
expect(jest.isMockFunction(mockDummyPromise)).toBeTruthy();
mockDummyPromise().then(data=>{
expect(data).not.toBeNull();
expect(data).toEqual('dummy dummy dummy');
})
})
})
Yes, esLint complains about the import from __mocks__
and also thinks that the mockDummyPromise
isn't really a promise, but this code works.
export const dummyPromise = () =>{
return new Promise((resolve)=>{
resolve('real dummy real dummy');
});
}
export const dummyPromise = () =>{
return new Promise( resolve => resolve('dummy dummy dummy'));
}
None of the above worked and in my case the problem was that I was adding a mock in a __mocks__
directory next to the file, but the import used a 'scoped module'. I had to add a folder for the scoped module under the root mocks folder ie __mocks__/@module/file.js
.
My issue was the resetMocks
problem as well. WOW... Was never going to find that one lol. THANK YOU @dstapleton92!!
@thisismydesign your solution helped me! Thanks
Solution:
Append --resetMocks=false
to your test script and re-run.
This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.
This issue was closed because it has been stalled for 30 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.
🐛 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
Other variations that also do nothing
```js // __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