看下面的自定义钩子。前提是当query
发生变化时,它会更新自己的状态。
export function UseCustomHook() {
const { query } = useRouter()
const [state, setState] = useState({})
useEffect(() => {
const updatedState = helperFunction(query)
setState(updatedState)
}, [query])
return state
}
目标是模拟useRouter
,但同时也更新它来专门测试"助手函数被调用n次,当查询更新n次">
我们可以用
模拟模块useRouter
jest.mock('next/router', () => ({
useRouter() {
return {
route: '/',
pathname: '',
query: {...},
asPath: '',
}
},
}))
但是这只是把它当作一个普通的模块。我想把它模拟成一个钩子,然后在
下面的测试中更新它describe('useCustomHook', () => {
it('should call helperFunction when query updates', () => {
const query = {...}
jest.spyOn(Router, 'useRouter' as any).mockImplementation(() => ({ query }))
const { result } = renderHook(() => useCustomHook())
expect(...)
})
})
您可以使用jest.mock()
模拟next/router
模块,useRouter
钩子及其返回值。在我们改变了query
的值之后,我们应该调用renderer函数来重新渲染自定义钩子,这样useEffect
钩子就会使用新的query
作为它的依赖项。
此外,我使用jest.spyOn()
添加spy onconsole.count()
方法来检查effect
函数调用的次数。
。
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);
});
});
测试结果:
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
包的版本:
"next": "^11.0.1",
"jest": "^26.6.3",
"ts-jest": "^26.4.4",
"react": "^16.14.0",