From Jest notes: Note: By default, jest.spyOn also calls the spied method.
In my Angular component.
ngAfterViewInit(): void {
this.offsetPopoverPosition();
}
In my spec:
it('ngAfterViewInit() method should call offsetPopoverPosition() method', () => {
const mockListener = jest.spyOn(cmp, 'offsetPopoverPosition');
const spy = mockListener.mockImplementation(() => {
console.log('in the mock');
});
cmp.ngAfterViewInit();
expect(spy).toHaveBeenCalled();
});
Simple. Yet the original function is still being called. I checked Jest 23.x docs: .x/jest-object#jestspyonobject-methodname .x/mock-function-api#mockfnmockimplementationfn
And few examples on the internets but I can't prevent jest from calling the original offsetPopoverPosition()
method.
Any ideas?
I am cross linking to Jest github issue which is for some reason closed without resolving it.
Jest spyOn() calls the actual function instead of the mocked
From Jest notes: Note: By default, jest.spyOn also calls the spied method.
In my Angular component.
ngAfterViewInit(): void {
this.offsetPopoverPosition();
}
In my spec:
it('ngAfterViewInit() method should call offsetPopoverPosition() method', () => {
const mockListener = jest.spyOn(cmp, 'offsetPopoverPosition');
const spy = mockListener.mockImplementation(() => {
console.log('in the mock');
});
cmp.ngAfterViewInit();
expect(spy).toHaveBeenCalled();
});
Simple. Yet the original function is still being called. I checked Jest 23.x docs: https://jestjs.io/docs/en/23.x/jest-object#jestspyonobject-methodname https://jestjs.io/docs/en/23.x/mock-function-api#mockfnmockimplementationfn
And few examples on the internets but I can't prevent jest from calling the original offsetPopoverPosition()
method.
Any ideas?
I am cross linking to Jest github issue which is for some reason closed without resolving it.
Jest spyOn() calls the actual function instead of the mocked
Share Improve this question edited May 21, 2019 at 5:24 skyboyer 23.7k7 gold badges61 silver badges71 bronze badges asked Apr 25, 2019 at 15:21 codeepiccodeepic 4,1028 gold badges37 silver badges59 bronze badges 4 |3 Answers
Reset to default 4From my experience, the issue is you're resetting the original mock's intent. When you create a spy, it has its own implementation, by overriding it with mockImplementation, I've experienced the scenario you are describing - instead, try this:
cmp.offsetPopoverPosition = jest.fn().mockImplementation(() => {
console.log('in the mock');
});
const mockListener = jest.spyOn(cmp, 'offsetPopoverPosition');
// ... do work
expect(mockListener).toHaveBeenCalled[Times,With]()
also this assumes that cmp
is an instance of the component and not just it's definition reference
edit: please note that mocking out a messaged function inside of the component you are testing is a misguided approach to unit testing. Instead of testing communication to the sameComponent.method
- test any messaging that chained method uses outside of the component being tested - With the brief question content, please ignore the testing approach advice I've given if its reading tea leaves and not relevant to your unit test design(s)
As suggested in the GitHub issue, the only thing that ended up working for me was to call the target function from the import of the same file. Something like this in React.
// cmp.js
import * as thisModule from './cmp';
offsetPopoverPosition = () => {}
ngAfterViewInit = () => {
thisModule.offsetPopoverPosition();
}
It's a weird issue...
The optimal solution does seem to just avoid this scenario by testing other items however (see this other answer).
I think two points are valid for this question. First, as the Jest documentation explains, jest.spyOn
also calls the spied method, so a custom implementation needs to be provided.
And second, a helper function is easier to mock if it is in a different file. If not, the tested function will look first for the helper in the same file, instead of the mocked one. This was explained here: https://stackoverflow.com/a/52318294/7478816
offsetPopoverPosition
bound tothis
in the component constructor? – Brian Adams Commented Apr 25, 2019 at 17:41cmp
is an instance so it wouldn't make a difference anyway. From what I can see of your code it looks like it should work. (The reason why JonathanHolvey's code in the github link doesn't work is becauseprocessVisit
is callingsaveVisit
directly so mocking the module export forsaveVisit
doesn't have any effect...that doesn't apply to your code since both of your functions are class methods from what I can see) – Brian Adams Commented Apr 25, 2019 at 18:44