You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 21:45:38