I have a React application to be tested. The application uses the useReducer()-Pattern and creates a dispatch function. As it´s neiter easy nor useful to assert on the state directly, I want to do my asserts against the input values of the dispatch function.
As I can´t spy on the dispatch function directly because it´s just a local function inside of a function component, my plan is to spy on the React.useReducer and mock it in a way that it returns a mocked dispatch function I can assert on.
I made a minimal example of this.
This is the component to be tested:
interface IState {
name : string
}
interface IAction {
type: "fetched data" | "manual update"
newName : string
}
const TestRedcuerComponent: React.FC<ITestComponentProps> = (props) => {
const { name } = props;
const initState = { name: name};
const handleUpdates = (state : IState, action : IAction) : IState => {
console.log("handle updates was called with " + action.newName);
return { name : action.newName };
}
const [state, dispatch] = React.useReducer(handleUpdates, initState);
React.useEffect(() => {
// In the real application, data like newName is fetched here and then passed to dispatch
//I´m interested in the input values of this function
dispatch({type: "fetched data", newName: "Max"});
}, [])
return (<div>
</div>)
}
export default TestRedcuerComponent;
This is how I test on it:
it("react specific test", async () => {
const mockedDispatcherFunction = jest.fn();
jest
//see information on why caller below
.spyOn(caller, 'useReducer')
.mockImplementationOnce((initialState, initializer) => [initialState, mockedDispatcherFunction]);
render(<TestReducerComponent name = { "Peter" }></TestReducerComponent>)
expect(mockedDispatcherFunction).toHaveBeenCalledWith({type: 'fetched data', initValues: {newName: "Max"} });
});
However, my mockedDispatcherFunction
is never called.
Why I used caller? I used barrel imports to be able to reexport the use-Reducer Function because otherwise I cannot redefine the property. (See: https://pyk.sh/tutorials/how-to-fix-cannot-redefine-property-x-typeerror-in-jest/)
My caller-Module
looks like this:
import { useReducer } from "react";
const caller = {useReducer}
export default caller;