You can use jest.mock() to mock next/router module, useRouter hook and its return value. After we changed the query value, we should call rerender function to rerender the custom hook, so that the useEffect hook will use the new query as its dependency.
Besides, I use jest.spyOn() to add spy on console.count() method to check how many times the effect function calls.
E.g.
useCustomHook.ts:
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
export function useCustomHook() {
const { query } = useRouter();
const [state, setState] = useState({});
useEffect(() => {
console.count('effect');
setState({ id: query.id });
}, [query]);
return state;
}
useCustomHook.test.ts:
import { useRouter } from 'next/router';
import { renderHook } from '@testing-library/react-hooks';
import { useCustomHook } from './useCustomHook';
import { mocked } from 'ts-jest/utils';
import { NextRouter } from 'next/dist/next-server/lib/router/router';
jest.mock('next/router');
const useMockRouter = mocked(useRouter);
describe('68660313', () => {
test('should pass', () => {
const countSpy = jest.spyOn(console, 'count');
const query1 = ({ query: { id: '1' } } as unknown) as NextRouter;
const query2 = ({ query: { id: '2' } } as unknown) as NextRouter;
useMockRouter.mockReturnValue(query1);
const { result, rerender } = renderHook(() => useCustomHook());
expect(result.current).toEqual({ id: '1' });
useMockRouter.mockReturnValue(query2);
rerender();
expect(result.current).toEqual({ id: '2' });
expect(countSpy).toBeCalledTimes(2);
});
});
test result:
PASS examples/68660313/useCustomHook.test.ts (7.664 s)
68660313
✓ should pass (32 ms)
console.count
effect: 1
at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
console.count
effect: 2
at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
useCustomHook.ts | 100 | 100 | 100 | 100 |
------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.184 s
packages' version:
"next": "^11.0.1",
"jest": "^26.6.3",
"ts-jest": "^26.4.4",
"react": "^16.14.0",