如何Mock带API调用的自定义React Hook?求测试示例
自定义useFetch Hook测试示例
我们可以用React Testing Library的renderHook测试自定义Hook,配合Jest模拟fetch API,下面是针对你的useFetch的完整测试示例:
依赖安装
先确保安装必要依赖:
npm install --save-dev @testing-library/react @testing-library/react-hooks jest
测试代码
创建useFetch.test.js文件,内容如下:
import { renderHook, waitFor } from '@testing-library/react'; import useFetch from './useFetch'; // 全局模拟fetch API global.fetch = jest.fn(); describe('useFetch Hook', () => { afterEach(() => { jest.clearAllMocks(); // 每次测试后清除mock调用记录 }); // 测试初始加载状态 it('should return isLoading as true initially', () => { const { result } = renderHook(() => useFetch('https://example.com/api')); expect(result.current.isLoading).toBe(true); expect(result.current.response).toBeUndefined(); }); // 测试成功获取数据的情况 it('should return data and set isLoading to false on successful fetch', async () => { const mockData = { id: 1, name: 'Test Data' }; // 模拟fetch成功响应 fetch.mockResolvedValueOnce({ ok: true, json: jest.fn().mockResolvedValueOnce(mockData), }); const { result } = renderHook(() => useFetch('https://example.com/api')); // 等待状态更新 await waitFor(() => { expect(result.current.isLoading).toBe(false); }); expect(result.current.response).toEqual(mockData); expect(fetch).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith('https://example.com/api'); }); // 测试请求失败的情况 it('should log error when fetch fails', async () => { const mockError = 'could not fetch the data for that resource'; // 模拟fetch响应状态异常 fetch.mockResolvedValueOnce({ ok: false, }); // 模拟console.log以捕获错误输出 const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); const { result } = renderHook(() => useFetch('https://example.com/api')); await waitFor(() => { // 原Hook失败时未更新isLoading,因此状态仍为true expect(result.current.isLoading).toBe(true); }); expect(consoleSpy).toHaveBeenCalledWith(mockError); expect(fetch).toHaveBeenCalledTimes(1); consoleSpy.mockRestore(); // 恢复原生console.log }); });
关键说明
renderHook: 专门用于测试自定义Hook的工具,能在测试环境中执行Hook并获取其返回值。jest.fn(): 创建Mock函数,用来模拟fetch和console.log,方便断言函数调用情况。waitFor: 等待Hook的异步状态更新,确保断言时状态已完成变化。afterEach: 每次测试后清除Mock调用记录,避免测试间相互干扰。
优化建议
你的useFetch目前未暴露错误状态,若需要更严谨的测试,可在Hook中添加error状态字段,这样就能直接断言错误信息,无需监听console.log。
内容的提问来源于stack exchange,提问作者developing_developer
相关产品推荐
相关产品推荐

