I am not expert in jest, but my recommendation to think about:
1) When the function is exported as default I use something like:
import Funct1 from "../../../src/components/Funct1";
...
jest.mock("../../../src/components/Funct1");
...
expect(Funct1).toHaveBeenCalledWith(params);
2) When the module (utils.js) has multiple exports as
export const f1 = () => {};
...
export const f8 = () => {};
You can try
import * as Utils from "../../../src/components/utils"
const f8Spy = jest.spyOn(Utils, 'f8');
...
expect(f8Spy).toHaveBeenCalledWith(params);
Similar discussion here
Answer from Dima Dorogonov on Stack Overflowtesting - How to spyOn a function that is not part of the class under test with Jest and Typescript - Stack Overflow
Cannot spy on individual functions that are individually exported
Jest mocked spy function, not being called in test
reactjs - Jest spy the external function issue - Stack Overflow
What Does Jest.clearallmocks() Function Do?
What Does the Jest.runonlypendingtimers() Function Do in the Program?
What Does Jest.restoreallmocks() Do?
I am not expert in jest, but my recommendation to think about:
1) When the function is exported as default I use something like:
import Funct1 from "../../../src/components/Funct1";
...
jest.mock("../../../src/components/Funct1");
...
expect(Funct1).toHaveBeenCalledWith(params);
2) When the module (utils.js) has multiple exports as
export const f1 = () => {};
...
export const f8 = () => {};
You can try
import * as Utils from "../../../src/components/utils"
const f8Spy = jest.spyOn(Utils, 'f8');
...
expect(f8Spy).toHaveBeenCalledWith(params);
Similar discussion here
Wrap your function with jest.fn. Like this:
const simpleFn = (arg) => arg;
const simpleFnSpy = jest.fn(simpleFn);
simpleFnSpy(1);
expect(simpleFnSpy).toBeCalledWith(1); // Passes test
Found great help from the answer here: Jest spyOn function called
This was the important step I was missing:
const instance = wrapper.instance()
const spy = jest.spyOn(instance, 'yearOnChange')
Updated working test with 2 working expects.
it('yearOnChange method is called', function() {
const instance = wrapper.instance(); // <-- Needed to do this here
const spy = jest.spyOn(instance, 'yearOnChange'); // <-- Then use instance here
wrapper.instance().forceUpdate();
const event = {
target: {
value: '1999'
}
};
wrapper.instance().yearOnChange(event);
wrapper.simulate('change', event);
const result = wrapper.state('year');
console.log('result', result); // result = 1999
expect(result).toEqual('1999');
expect(spy).toHaveBeenCalled();
});
You are spying and calling yearOnChange manually.
Try not calling wrapper.instance().yearOnChange(event);
Call the wrapper.instance().onChange event, or like you did, run the simulate('change') will be enough.
You could also try VehiclePicker.prototype.yearOnChange = jest.fn()
expect(VehiclePicker.prototype.yearOnChange).toBeCalled();
When you call the jest.spyOn method you have to provide as first argument the object that contains the method you want to spy (documentation).
You are probably importing the handleError method like:
import { handleError } from 'file-where-handle-error-is';
Therefore, your imported handleError is directly the function and not an object that contains the function.
To solve your problem you can import the module where handleError is located and then mock the handleError method:
const utils = require('file-where-handle-error-is');
const spyHandleError = jest.spyOn(utils, 'handleError');
Another solution would be to mock the module where handleError is located with jest.mock:
jest.mock('../../../src/utils/handle-error', () => {
return {
handleError: jest.fn()
};
If you wish to spy on a function that is exported from a file that contains many other functions (such as a helper file), then you can import all functions as an object like so:
import * as errorHelpers from 'path/to/errorHelpers';
Then you can set up your spy as follows:
const spyHandleError = jest.spyOn(errorHelpers, 'handleError');