如何用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
相关产品推荐
相关产品推荐

