Jest 提供了多种测试 React Hooks 的方法,主要使用 @testing-library/react-hooks:
1. 测试 useState:
javascriptimport { renderHook, act } from '@testing-library/react-hooks'; test('useState hook', () => { const { result } = renderHook(() => useCounter(0)); expect(result.current.count).toBe(0); act(() => { result.current.increment(); }); expect(result.current.count).toBe(1); });
2. 测试 useEffect:
javascripttest('useEffect hook', () => { const { result } = renderHook(() => useFetch('/api/data')); expect(result.current.loading).toBe(true); await act(async () => { await waitFor(() => !result.current.loading); }); expect(result.current.data).toBeDefined(); });
3. 测试 useContext:
javascripttest('useContext hook', () => { const wrapper = ({ children }) => ( <ThemeContext.Provider value="dark"> {children} </ThemeContext.Provider> ); const { result } = renderHook(() => useTheme(), { wrapper }); expect(result.current.theme).toBe('dark'); });
4. 测试自定义 Hook:
javascriptfunction useCustomHook(initialValue) { const [value, setValue] = useState(initialValue); const double = useMemo(() => value * 2, [value]); return { value, setValue, double }; } test('custom hook', () => { const { result } = renderHook(() => useCustomHook(5)); expect(result.current.value).toBe(5); expect(result.current.double).toBe(10); act(() => { result.current.setValue(10); }); expect(result.current.double).toBe(20); });
5. 测试异步 Hook:
javascripttest('async hook', async () => { const { result, waitForNextUpdate } = renderHook(() => useAsyncData()); expect(result.current.loading).toBe(true); await waitForNextUpdate(); expect(result.current.loading).toBe(false); expect(result.current.data).toBeDefined(); });
6. 测试错误处理:
javascripttest('hook error handling', async () => { const { result, waitForNextUpdate } = renderHook(() => useFetch('/invalid')); await waitForNextUpdate(); expect(result.current.error).toBeInstanceOf(Error); });
最佳实践:
- 使用
renderHook测试 Hook - 使用
act包装状态更新 - 测试 Hook 的初始状态和更新后的状态
- 测试异步 Hook 时使用
waitFor或waitForNextUpdate - 测试错误边界情况
- 保持测试简单,专注于 Hook 的行为