如何在Jest中测试React Suspense的Axios Promise包装器
React Suspense 适配 useAxios Hook 的单元测试问题解决
问题背景
已实现适配React Suspense的useAxios Hook及promiseWrapper包装器,应用运行正常,但编写Jest单元测试时遇到两个问题:
- 错误场景测试无法抛出预期错误
- 不知如何模拟pending状态的行为
原错误场景测试代码:
it('should call endpoint and throw error on exception', async () => { mockedAxios.request.mockRejectedValueOnce(new Error('error')); expect(() => { renderHook(() => useAxios<TestResponseType>({})) }).toThrowError(); });
解决方案
1. 修复错误场景测试
原测试的核心问题:
useAxios返回的是promiseWrapper生成的函数,而非直接抛出错误,必须调用该函数才会触发错误抛出逻辑- 异步操作需要用
async/await配合waitFor处理状态更新
修正后的测试代码:
import { renderHook, waitFor } from '@testing-library/react'; it('should throw error when request fails', async () => { mockedAxios.request.mockRejectedValueOnce(new Error('error')); const { result } = renderHook(() => useAxios<TestResponseType>({})); // 等待useEffect执行完成,response更新为包装函数 await waitFor(() => expect(result.current).not.toBeNull()); // 调用返回的函数,断言是否抛出预期错误 expect(() => result.current()).toThrowError('error'); });
2. 模拟pending状态测试
要测试pending状态,需让Axios返回一个未决议的Promise,验证调用Hook返回的函数时会抛出该Promise:
it('should throw suspender promise when in pending state', async () => { // 创建一个始终处于pending状态的Promise const pendingPromise = new Promise(() => {}); mockedAxios.request.mockReturnValueOnce(pendingPromise); const { result } = renderHook(() => useAxios<TestResponseType>({})); // 等待response被设置为包装函数 await waitFor(() => expect(result.current).not.toBeNull()); // 调用函数,断言抛出的是pending状态的Promise expect(() => result.current()).toThrow(pendingPromise); });
关键说明
promiseWrapper返回的函数只有在被调用时,才会根据当前状态抛出Promise/错误或返回数据,测试时必须主动调用该函数- 需使用
waitFor确保useEffect执行完成,response状态更新为包装函数后再进行断言
内容的提问来源于stack exchange,提问作者C A Mc
相关产品推荐
相关产品推荐

