返回404后msw处理器导致react-query持续处于isLoading状态
问题原因与解决方案
核心原因
你的测试失败是因为React Query默认的重试机制:当请求返回404这类错误状态时,React Query会自动重试请求(默认3次),在重试过程中,钩子的isLoading状态会一直保持true,不会立刻切换到isError,导致waitFor里的断言超时失败。
另外还有一个潜在问题:fetch API收到4xx/5xx状态码时不会自动抛出异常,如果你的usePost钩子没有手动处理这种情况,React Query会把404的响应当成成功结果,永远不会进入错误状态。
解决方案
1. 修改usePost钩子,处理错误并禁用重试
在usePost的useQuery配置中禁用重试,同时手动处理fetch的错误状态:
// usePost.js import { useQuery } from 'react-query'; export default function usePost(postId) { return useQuery( ['post', postId], async () => { const res = await fetch(`https://your-wordpress-site.com/wp-json/wp/v2/posts/${postId}`); // 关键:手动处理非2xx状态码,抛出异常让React Query识别为错误 if (!res.ok) { const errorData = await res.json(); throw new Error(errorData.message || `Request failed with status ${res.status}`); } return res.json(); }, { retry: 0, // 禁用自动重试,失败后直接进入错误状态 } ); }
2. 仅在测试中临时禁用重试
如果不想修改钩子的默认行为,可以在测试的QueryClient中全局设置重试配置:
// 测试文件中修改queryClient初始化 const queryClient = new QueryClient({ defaultOptions: { queries: { retry: 0, // 全局禁用重试,仅作用于测试 }, }, });
或者针对单个测试的钩子传递配置(如果usePost支持接收额外的useQuery选项):
it('should handle fetch errors', async () => { const postId = 'nonexistent-post'; const { result } = renderHook(() => usePost(postId, { retry: 0 }), { wrapper, }); await waitFor(() => { expect(result.current.isLoading).toBeFalsy(); expect(result.current.isError).toBeTruthy(); }); expect(result.current.error).toBeInstanceOf(Error); });
内容的提问来源于stack exchange,提问作者Enrique Moreno Tent
相关产品推荐
相关产品推荐

