I want to test if the ponent is dispatching an action to the store, for this, i have to mock the functionalities of React Hooks.
I'm using the useDispatch hook to get the dispatcher function and put inside a variable so them i can call it.
When i run my test suits, even if the useDispatch function is mocked, it returns an error saying that it's not a function.
jest.mock('react-redux', () => ({
useSelector: jest.fn(),
useDispatch: jest.fn(() => {}),
}));
it('should be able open modal', () => {
const { getByTestId } = render(<Dropdown />);
fireEvent.click(getByTestId('dropdown'));
fireEvent.click(getByTestId('button-Transactions'));
const dispatch = jest.fn();
useDispatch.mockReturnValue(dispatch);
expect(dispatch).toHaveBeenCalledWith(openModal('transactions'));
});
The error:
TypeError: dispatch is not a function
19 |
20 | if (item.action) {
> 21 | dispatch(item.action);
| ^
22 | }
23 |
24 | return item;
My ponent:
const history = useHistory();
const dispatch = useDispatch();
function handleNavigation(item) {
if (item.path) return history.push(item.path);
if (item.action) {
dispatch(item.action);
}
return item;
}
I want to test if the ponent is dispatching an action to the store, for this, i have to mock the functionalities of React Hooks.
I'm using the useDispatch hook to get the dispatcher function and put inside a variable so them i can call it.
When i run my test suits, even if the useDispatch function is mocked, it returns an error saying that it's not a function.
jest.mock('react-redux', () => ({
useSelector: jest.fn(),
useDispatch: jest.fn(() => {}),
}));
it('should be able open modal', () => {
const { getByTestId } = render(<Dropdown />);
fireEvent.click(getByTestId('dropdown'));
fireEvent.click(getByTestId('button-Transactions'));
const dispatch = jest.fn();
useDispatch.mockReturnValue(dispatch);
expect(dispatch).toHaveBeenCalledWith(openModal('transactions'));
});
The error:
TypeError: dispatch is not a function
19 |
20 | if (item.action) {
> 21 | dispatch(item.action);
| ^
22 | }
23 |
24 | return item;
My ponent:
const history = useHistory();
const dispatch = useDispatch();
function handleNavigation(item) {
if (item.path) return history.push(item.path);
if (item.action) {
dispatch(item.action);
}
return item;
}
Share
Improve this question
edited Apr 9, 2020 at 16:56
Laura Beatris
asked Apr 9, 2020 at 16:24
Laura BeatrisLaura Beatris
1,9329 gold badges31 silver badges57 bronze badges
2 Answers
Reset to default 3The ponent was trying to execute a function that wasn't declared yet. We need to mock before of the render method
const dispatch = jest.fn();
useDispatch.mockReturnValue(jest.fn());
const dropdown = render(<Dropdown />);
It is because when you mocked it, you haven't specified a value.
I thought of two ways to do this:
- Having a real store in your test, so you can test the integration:
const mockedStore = { /* the things you need in store in your test */ };
const store = configureStore(mockedStore, browserHistory);
const { getByTestId } = render(<Provider store={store}><Dropdown /></Provider>);
- Mock your
dispatch
, but you ll end up having infinite issues withuseSelector
(especially if you have more than one useSelector in the tree you rendered).
import * as ReactRedux from 'react-redux';
// useDispatch returns a function which we are mocking here
const mockDispatch = jest.fn();
beforeAll(() => {
ReactRedux.useDispatch = jest.fn().mockImplementation(() => mockDispatch);
});
beforeEach(() => {
ReactRedux.useDispatch.mockClear();
});
expect(mockDispatch).toHaveBeenCalledWith(yourAction);
Please note that the real issue you will face is not with dispatch, but with useSelector
.
If you mock it, it will return the value you want. But what if you have more than one in your tree ? for that, I real store is necessary as far as I know.