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

如何用Jest测试自定义Hook useRegionOptions的排序功能?

自定义Hook排序功能的Jest测试问题及修复

我是JavaScript、React和Jest新手,在为自定义Hook的排序功能编写Jest测试时遇到困难。尝试mock接口返回["C", "B", "A"],期望Hook返回排序后的["A", "B", "C"],但多次尝试都没成功。

自定义Hook代码

export const useRegionOptions = (list, client) => {
    const { setFieldTouched } = useFormikContext();
    const [regionOptions, setRegionOptions] = useState([]);

    useEffect(() => {
        async function getRegionOptions() {
            return (
                await fetch(
                    `url/region/${client}`,
                    {
                        method: 'GET',
                        headers: {
                            'Content-Type': 'application/json'
                        }
                    }
                )
            ).json();
        }

        if (!!client) {
            getRegionOptions()
                .then(regionList => {
                    setRegionOptions([...regionList].sort());
                    setFieldTouched('region');
                })
                .catch(error => {
                    console.error(error);
                })
        }
    }, [client]);

    return {
        regionOptions,
        setRegionOptions
    };
};

原测试代码

describe('useRegionOptions', () => {
    it('should list elements alphabetically', async () => {

        global.fetch = jest.fn( () =>
            Promise.resolve( {
                json: () => Promise.resolve({['C', 'B', 'A'] }),
            })
        );

        const { result, waitForNextUpdate } = renderHook(() => useRegionOptions('list', 'client'))

        await waitForNextUpdate();

        expect(result.current.value).toBe(['A', 'B', 'C']);

    })

});

问题分析及修复

测试代码存在几个关键错误:

  • Fetch Mock格式错误:返回的{['C', 'B', 'A']}是无效对象语法,Hook期望接口返回数组,应直接返回["C", "B", "A"]
  • 断言属性错误:Hook返回的是包含regionOptions的对象,而非value,需访问result.current.regionOptions
  • 数组比较方法错误:toBe做严格引用比较,数组是引用类型,要用toEqual比较内容
  • 未Mock Formik上下文:Hook依赖useFormikContext,测试环境无该上下文会报错,需提前mock

修正后的测试代码

import { renderHook, waitForNextUpdate } from '@testing-library/react';
import { useFormikContext } from 'formik';
import { useRegionOptions } from './path-to-your-hook';

// Mock Formik上下文
jest.mock('formik', () => ({
    useFormikContext: jest.fn(() => ({
        setFieldTouched: jest.fn()
    }))
}));

describe('useRegionOptions', () => {
    it('should list elements alphabetically', async () => {
        // Mock fetch接口返回未排序的数组
        global.fetch = jest.fn(() =>
            Promise.resolve({
                json: () => Promise.resolve(["C", "B", "A"])
            })
        );

        const { result } = renderHook(() => useRegionOptions('list', 'client'));

        // 等待Hook完成异步更新
        await waitForNextUpdate();

        // 断言排序后的结果
        expect(result.current.regionOptions).toEqual(["A", "B", "C"]);
        // 可选:断言setFieldTouched被调用
        expect(useFormikContext().setFieldTouched).toHaveBeenCalledWith('region');
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 19:53:11