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

如何在JEST中不使用mock,通过async/await测试React Hooks的异步API调用

问题根源梳理

  1. 你测试时booths始终为空的核心原因有两个:
  • 原Hook中的fetchBooths方法没有返回Promise,你用await等待时无法感知到异步请求结束,断言执行时接口还未拿到返回结果,状态还停留在初始值
  • 之前的测试代码直接mock了fetchBooths方法,完全替换了原有逻辑,不会触发真实API调用和全局状态的dispatch

第一步:先修改原Hook的useFetchBooths

给fetchBooths加上return,返回请求的Promise实例,方便测试时等待异步完成:

// 省略其他未改动的代码
function fetchBooths(){
    setIsLoading(true)
    // 新增return返回请求Promise
    return request.get('/event/get-booth-list')
        .then((res) => {
            setIsLoading(false)
            if (res)
            {
                dispatch({
                    type: SET_BOOTHS,
                    payload: res.data.booth_data
                })
            }
            return res
        })
}

第二步:真实API调用测试用例

测试前请确保测试环境可正常访问后端接口,若接口需要鉴权,可在beforeAll钩子中提前完成身份初始化、设置请求头token等操作:

import { renderHook, act } from '@testing-library/react-hooks';
import useFetchBooths from "../../../utils/hooks/useFetchBooths";
import { Store } from "../../../utils/store/context/store";

describe("hook: useFetchBooths", () => {
    // 测试真实API拉取展位数据
    test('真实接口调用成功,booths数据正常更新', async () => {
        const wrapper = ({ children }) => <Store>{children}</Store>
        const { result } = renderHook(() => useFetchBooths(), { wrapper });

        // 调用拉取方法,等待请求完全结束
        await act(async () => {
            await result.current.fetchBooths();
        });

        // 校验加载状态结束
        expect(result.current.isLoading).toBe(false);
        // 校验booths已填充了真实数据,不为空
        expect(result.current.booths.length).toBeGreaterThan(0);
    });

    // 测试searchBooths功能
    test('searchBooths按关键词正确过滤展位', async () => {
        const wrapper = ({ children }) => <Store>{children}</Store>
        const { result } = renderHook(() => useFetchBooths(), { wrapper });

        // 先拉取全量展位数据
        await act(async () => {
            await result.current.fetchBooths();
        });
        const originalTotal = result.current.booths.length;
        expect(originalTotal).toBeGreaterThan(0);

        // 取第一个展位名称作为搜索关键词,保证匹配结果存在
        const validSearchKey = result.current.booths[0].booth_name;
        act(() => {
            result.current.searchBooths(validSearchKey);
        });

        // 校验过滤结果全部匹配关键词
        result.current.booths.forEach(booth => {
            expect(booth.booth_name.toLowerCase()).toContain(validSearchKey.toLowerCase());
        });

        // 测试空关键词重新拉取全量数据
        await act(async () => {
            result.current.searchBooths('');
        });
        expect(result.current.booths.length).toBe(originalTotal);

        // 测试不存在的关键词重新拉取全量数据
        await act(async () => {
            result.current.searchBooths('不存在的展位名称123456');
        });
        expect(result.current.booths.length).toBe(originalTotal);
    });
});

注意事项

  • 真实API测试属于集成测试范畴,依赖后端服务正常运行、网络可访问,执行速度会比Mock接口的单元测试慢
  • 如果测试环境存在跨域限制,需要在测试配置中开启代理或者修改接口请求域名的跨域配置,保证request.get可正常请求到数据

内容的提问来源于stack exchange,提问作者Arslaan Muhammad Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 10:54:02