mock useDispatch in jest and test the params with using that dispatch action in functional component
[upd] I've changed my mind dramatically since then. Now I think mocking store(with redux-mock-store
or even real store that changes its state) - and wrapping component with <Provider store={mockedStore}>
- is way more reliable and convenient. Beware.
if you mock react-redux
you will be able to verify arguments for useDispatch
call. Also in such a case you will need to re-create useSelector
's logic(that's really straightforward and actually you don't have to make mock be a hook). Also with that approach you don't need mocked store or <Provider>
at all.
import { useSelector, useDispatch } from 'react-redux';
const mockDispatch = jest.fn();
jest.mock('react-redux', () => ({
useSelector: jest.fn(),
useDispatch: () => mockDispatch
}));
it('loads data on init', () => {
const mockedDispatch = jest.fn();
useSelector.mockImplementation((selectorFn) => selectorFn(yourMockedStoreData));
useDispatch.mockReturnValue(mockedDispatch);
mount(<Router><Clients history={historyMock} /></Router>);
expect(mockDispatch).toHaveBeenCalledWith(/*arguments your expect*/);
});
import * as redux from "react-redux";
describe('dispatch mock', function(){
it('should mock dispatch', function(){
//arrange
const useDispatchSpy = jest.spyOn(redux, 'useDispatch');
const mockDispatchFn = jest.fn()
useDispatchSpy.mockReturnValue(mockDispatchFn);
//action
triggerYourFlow();
//assert
expect(mockDispatchFn).toHaveBeenCalledWith(expectedAction);
//teardown
useDispatchSpy.mockClear();
})
}});
From functional component we mock dispatch like above to stop it to execute the real implementation. Hope it helps!