I am trying to mock history.push inside the new useHistory hook on react-router and using @testing-library/react. I just mock
Use jest.mock in module scope will automatically be hoisted to the top of the code block. So that you can get the mocked version react-router-dom in NotFound.jsx file and your test file.
Besides, we only want to mock useHistory hook, so we should use jest.requireActual() to get the original module and keep other methods as the original version.
Here is the solution:
NotFound.jsx:
import React from 'react';
import { useHistory } from 'react-router-dom';
const RouteNotFound = () => {
const history = useHistory();
return (
);
};
export default RouteNotFound;
NotFound.test.jsx:
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { render, fireEvent } from '@testing-library/react';
import RouteNotFound from './NotFound';
const mockHistoryPush = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory: () => ({
push: mockHistoryPush,
}),
}));
describe('RouteNotFound', () => {
it('Redirects to correct URL on click', () => {
const { getByRole } = render(
,
);
fireEvent.click(getByRole('button'));
expect(mockHistoryPush).toHaveBeenCalledWith('/help');
});
});
Unit test result with 100% coverage:
PASS src/stackoverflow/58524183/NotFound.test.jsx
RouteNotFound
✓ Redirects to correct URL on click (66ms)
--------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
NotFound.jsx | 100 | 100 | 100 | 100 | |
--------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.133s, estimated 11s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58524183