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

React 18项目中用nock+react-query测试自定义hook遇问题求助

React Query自定义Hook测试:result.current undefined且一直处于loading状态的解决办法

核心原因分析

1. result.current 出现undefined的原因

初始渲染阶段React尚未完成Hook执行时,直接访问result.current会拿到undefined,但如果在waitFor回调内仍出现该问题,大概率是你的createQueryProviderWrapper未正确配置QueryClientProvider——比如没有创建有效的QueryClient实例,导致React Query上下文未注入,Hook无法正常初始化。

2. 查询一直处于loading的关键原因

最常见的问题是nock域名与实际请求域名不匹配:
你的getUserProfileAPI中使用fetch('v1/me')是相对路径,实际请求会发送到测试环境默认域名(如http://localhost:3000/v1/me),但你用nock模拟的是https://api.example.com,导致nock无法拦截请求,真实请求挂起,查询一直停留在loading状态。

3. 配置中遗漏的关键点

  • 未给QueryClient配置测试友好的参数(如关闭重试)
  • nock域名与实际请求域名不匹配
  • 测试中仅打印日志未添加断言,无法触发waitFor的等待逻辑

具体修复步骤

步骤1:修正nock的域名匹配

如果getUserProfileAPI使用相对路径,修改nock匹配测试环境域名:

// 匹配测试环境默认域名(示例为localhost:3000)
nock("http://localhost:3000")
  .get("/v1/me")
  .reply(200, {
    data: {
      id: 1,
      firstName: "value from the api",
    },
  });

或者修改getUserProfileAPI使用绝对路径,确保和nock域名一致:

// getUserProfileAPI中使用绝对路径
export const getUserProfileAPI = () => {
  return fetch("https://api.example.com/v1/me").then(res => res.json());
};

步骤2:确保createQueryProviderWrapper配置正确

检查测试工具函数是否正确创建QueryClient并提供上下文,建议关闭重试避免测试超时:

// @/test/index.js
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactNode } from 'react';

export const createQueryProviderWrapper = () => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false, // 测试时关闭重试
        refetchOnWindowFocus: false,
      },
    },
  });

  return ({ children }: { children: ReactNode }) => (
    <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  );
};

步骤3:修改测试逻辑,添加断言

在waitFor中添加断言,确保等待到查询成功,而非仅打印日志:

test("should fetch user profile and have correct nickname", async () => {
  nock("https://api.example.com")
    .get("/v1/me")
    .reply(200, {
      data: {
        id: 1,
        firstName: "value from the api",
      },
    });

  const { result } = setupHook();

  // 等待查询成功
  await waitFor(() => {
    expect(result.current.isSuccess).toBe(true);
  });

  // 断言数据正确性
  expect(result.current.data.data.firstName).toBe("value from the api");
});

额外检查点

  • 确认getUserProfileAPI返回有效Promise,无语法错误或未处理异常
  • 测试前添加nock.cleanAll()清理旧模拟,避免干扰
  • 若使用Jest,确保测试环境支持fetch(可安装whatwg-fetch并在setupFiles中引入)

内容的提问来源于stack exchange,提问作者Michael Luo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:20:25