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

使用Jest测试React Query组件时result返回null的原因排查

为什么测试中result返回null?

我希望测试组件在从查询获取数据后是否正常渲染,但测试时result返回null;用自定义Hook测试时也出现相同错误,推测是数据调用方式有问题。

相关代码

获取函数

const fetchWeather = async (lat: number, lon: number) => {
  const response = await fetch(`${OW_API_URL}forecast?lat=${lat}&lon=${lon}&${OWApiKey}`);
  const weather= await response.json();
  return weather;
};

组件代码

const { data } = useQuery(
    ['weather'],
    () => fetchWeather(latitude, longitude),
);

return (
    <div>
      {data ? (<p>Data recieved</p>) : (<p>Data's empty</p>)}
    </div>
);

测试代码

const queryClient = new QueryClient();

const componentProps = {
    latitude: 50,
    longitude: 50,
};

const wrapper = () => (
    <QueryClientProvider client={queryClient}>
        <Weather latitude={componentProps.latitude} longitude={componentProps.latitude} />
    </QueryClientProvider>
);

const { result } = renderHook(() => fetchNextWeather(componentProps.latitude, componentProps.longitude), { wrapper });

await waitFor(() => result.current);

expect(result).toBe(true);

报错信息

- true"
+ "Object {
+   "current": null,
+ }"

自定义Hook代码

function useCustomHook() {
    return useQuery({ queryKey: ['customHook'], queryFn: () => 'Hi' });
}

自定义Hook测试代码

const { result } = renderHook(() => useCustomHook(), { wrapper });
await waitFor(() => result.current);

问题原因分析

1. 误用renderHook调用普通异步函数

renderHook是用来测试自定义Hook的工具,不是用来执行普通异步函数的。你直接用它调用fetchWeather(测试里的fetchNextWeather是笔误),在测试环境(如Jest)中如果没有Mock真实的fetch请求,会导致请求失败,最终result.current返回null。

2. 测试断言逻辑完全错误

expect(result).toBe(true); 完全不符合逻辑:result是renderHook返回的对象,结构为{ current: ... },不可能等于true。你需要断言的是数据是否正确返回,比如Hook返回的data字段。

3. 自定义Hook的等待逻辑错误

对于useCustomHook的测试,await waitFor(() => result.current); 没有意义——useQuery会立即返回一个对象(result.current一开始就存在),只是对象里的data初始为undefined,直到请求完成。正确的等待应该是判断data是否存在或请求是否成功。

4. 测试代码中的笔误

测试的wrapper里,Weather组件的longitude传成了componentProps.latitude,虽然这不是当前null问题的直接原因,但会导致组件使用错误的经纬度请求数据。

修正后的测试示例

组件测试(正确方式)

用render渲染组件,同时MockfetchWeather避免真实网络请求:

import { render, screen, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import Weather from './Weather';
import { fetchWeather } from './path-to-fetch-function';

// Mock异步请求函数
jest.mock('./path-to-fetch-function', () => ({
  fetchWeather: jest.fn().mockResolvedValue({ mockData: 'test' }),
}));

test('Weather组件获取数据后渲染正确内容', async () => {
  const queryClient = new QueryClient();
  const props = { latitude: 50, longitude: 50 };

  render(
    <QueryClientProvider client={queryClient}>
      <Weather {...props} />
    </QueryClientProvider>
  );

  // 等待数据加载完成,断言渲染的内容
  await waitFor(() => {
    expect(screen.getByText('Data recieved')).toBeInTheDocument();
  });
});

自定义Hook测试(正确方式)

import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import useCustomHook from './useCustomHook';

const queryClient = new QueryClient();
const wrapper = ({ children }) => (
  <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);

test('useCustomHook能正确返回数据', async () => {
  const { result } = renderHook(() => useCustomHook(), { wrapper });

  await waitFor(() => {
    expect(result.current.data).toBe('Hi');
    expect(result.current.isSuccess).toBe(true);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:10:18