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

React Testing Library测试React Query时Promise未解决导致超时问题

React 18 + React Query 3.3 测试超时问题修复与调试方案

一、先从核心配置排查

1. 核对React Query测试实例配置

React Query 3.x在测试环境下的Suspense模式必须明确配置,别漏了这几点:

  • 测试用的QueryClient一定要把defaultOptions.queries.suspense设为true,同时关掉重试(retry: false),不然重试机制会让请求一直pending
  • 示例配置:
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true,
      retry: false,
    },
  },
});

2. 确认请求模拟完全匹配

不管用msw还是其他mock工具,务必保证:

  • 请求的URL、HTTP方法、查询参数和组件里useQuery调用的完全一致,差一个字符都会导致请求挂起
  • mock的响应不能抛错,返回的格式要和组件预期的结构匹配
  • 举个msw的正确示例:
rest.get('/api/user/list', (req, res, ctx) => {
  return res(ctx.json([{ id: 1, name: 'test' }]));
});

3. 检查RTL的渲染逻辑

  • 每个测试用例都要新建独立的QueryClient实例,别复用,避免缓存污染
  • 组件必须同时被QueryClientProvider和Suspense包裹,渲染顺序别搞反
  • 别在渲染前就调用waitFor,先渲染组件,再等目标内容出现:
render(
  <QueryClientProvider client={queryClient}>
    <Suspense fallback={<div>Loading...</div>}>
      <YourTargetComponent />
    </Suspense>
  </QueryClientProvider>
);

await waitFor(() => screen.getByText('加载完成后的内容'));

二、深度调试技巧

1. 打印QueryClient的查询状态

在测试里加日志,直接看查询的缓存和状态:

console.log('data1缓存:', queryClient.getQueryData('data1-key'));
console.log('data1状态:', queryClient.getQueryState('data1-key')); // 能看到是pending/error还是success

2. 给useQuery加回调跟踪

在组件的useQuery里加onSuccess和onError,确认请求到底有没有触发:

const { data } = useQuery('data1-key', fetchData1, {
  onSuccess: () => console.log('data1请求成功了'),
  onError: (err) => console.log('data1请求炸了:', err),
});

3. 临时禁用缓存排查问题

测试里把缓存时间和过期时间都设为0,强制触发请求,排除缓存导致的异常:

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true,
      retry: false,
      cacheTime: 0,
      staleTime: 0,
    },
  },
});

4. 核对库版本兼容性

React 18的Suspense对测试库要求较高,确认RTL 14.0.0完全适配React 18的并发特性,另外React Query 3.3版本有点老,建议升级到3.x的最新稳定版,说不定是旧版的兼容bug

三、容易踩的坑

  • 请求Key不匹配:组件里useQuery的key是['user', 123],测试模拟时用了'user'当key,导致查询匹配失败,一直pending
  • 漏加Suspense包裹:虽然QueryClient开了suspense: true,但组件没被Suspense包起来,测试时直接报错或挂起
  • Mock工具没正确启动:比如msw的server.listen()没在测试前调用,或者server.resetHandlers()没清理旧mock,导致请求没被拦截

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:12:17