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

使用renderHook测试useFetch自定义Hook时无法获取API返回数据

如何正确测试useFetch自定义Hook?

你编写了useFetch自定义Hook用于获取产品数据,在测试时使用renderHook始终拿到空的products数组,即使尝试waitFor也无法获取API返回结果。问题的核心在于测试时直接依赖真实API会导致异步状态未更新就断言,且真实接口不稳定,必须通过mock fetch配合异步测试工具来解决。

解决方案:Mock Fetch + 异步状态等待

1. Mock全局Fetch接口

在测试中模拟fetch的返回值,避免调用真实API,确保测试稳定且快速。以下是完整的测试代码示例:

import { renderHook, waitFor } from "@testing-library/react";
import { expect, vi } from "vitest";
import { useFetch } from "../../hooks/useFetch";

// Mock全局fetch方法,模拟API返回数据
vi.spyOn(global, 'fetch').mockResolvedValue({
  json: async () => ({
    products: Array(30).fill({ id: 1, title: "测试产品" }),
    total: 100
  })
});

describe("Products组件", () => {
  // 测试初始加载30条产品
  test("正确渲染第一页的30个产品", async () => {
    const { result } = renderHook(() => useFetch());

    // 等待products状态更新完成
    await waitFor(() => {
      expect(result.current.products.length).toBe(30);
    });

    // 验证fetch是否被正确调用
    expect(fetch).toHaveBeenCalledWith(
      "https://dummyjson.com/products?skip=0&limit=30"
    );
  });

  // 测试翻页功能
  test("触发下一页时获取正确的数据", async () => {
    const { result } = renderHook(() => useFetch());

    // 调用翻页方法到第2页
    result.current.handleNextPage(2);

    await waitFor(() => {
      expect(result.current.products.length).toBe(30);
    });

    // 验证fetch的参数是否符合分页逻辑
    expect(fetch).toHaveBeenCalledWith(
      "https://dummyjson.com/products?skip=30&limit=30"
    );
  });

  // 测试结束后恢复原始fetch实现,避免影响其他测试
  afterEach(() => {
    global.fetch.mockRestore();
  });
});

2. 关键注意点

  • 必须使用async/await + waitFor:Hook内部的useEffect会触发异步fetch,初始状态是空数组,必须等待状态更新后再断言。
  • Mock fetch是必要的:真实API依赖外部服务,测试时可能因网络、服务状态导致失败,mock后测试完全可控。
  • 验证fetch调用参数:确保Hook的分页逻辑正确,比如第2页时skip参数应为30((2-1)*30)。

为什么之前的waitFor没生效?

大概率是没有mock fetch,测试环境中真实的fetch请求被阻止或超时,导致products状态永远无法更新。mock fetch后,请求会立即返回模拟数据,waitFor就能捕获到状态变化。

内容的提问来源于stack exchange,提问作者Matheus Oliveira Damião

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 19:13:16