如何测试Context中API调用失败的场景?
解决Context API重构后API调用失败的测试问题
问题分析
重构后useAgent移至PanelContextProvider中,原直接mock axios的方式因组件不再直接调用useAgent失效;同时你之前的测试代码里,模拟Context的error是字符串而非Error实例,导致组件渲染error.message时得到undefined,这也是测试失败的核心原因之一。
以下提供两种可行的测试方案:
方案一:复用Axios Mock,配合真实Context Provider
该方案贴近真实运行流程,验证从API请求失败到Context传递错误再到组件渲染的完整链路:
import React, { useContext } from 'react'; import { render, screen, renderHook } from '@testing-library/react'; import AgentInformationPanel from './AgentInformationPanel.js'; import { PanelContextProvider, PanelContext } from '../../contexts/Panel.context.js'; import axios from 'axios'; jest.mock('axios'); test('API调用失败时渲染错误消息', async () => { // 模拟axios请求失败,返回Error实例 axios.get.mockRejectedValue(new Error('Something went wrong D:')); // 渲染真实的Context Provider和目标组件 render( <PanelContextProvider> <AgentInformationPanel /> </PanelContextProvider> ); // 通过renderHook获取Context方法,触发面板渲染和API请求 const { result } = renderHook(() => useContext(PanelContext), { wrapper: PanelContextProvider }); // 设置agentID并开启面板渲染 result.current.setDataForPanel('test-agent-id'); // 等待错误消息出现并断言 const errorElement = await screen.findByText('Error: Something went wrong D:'); expect(errorElement).toBeInTheDocument(); });
方案二:Mock自定义Hook useAgent
若无需测试axios请求细节,可直接mockuseAgent让它返回错误状态,更专注于组件的错误渲染逻辑:
import React, { useContext } from 'react'; import { render, screen, renderHook } from '@testing-library/react'; import AgentInformationPanel from './AgentInformationPanel.js'; import { PanelContextProvider, PanelContext } from '../../contexts/Panel.context.js'; import { useAgent } from '../hooks/useAgent.js'; // Mock整个useAgent hook jest.mock('../hooks/useAgent', () => ({ useAgent: jest.fn() })); test('API调用失败时渲染错误消息', async () => { // 让useAgent直接返回包含Error实例的错误状态 useAgent.mockReturnValue({ agent: null, loading: false, error: new Error('Something went wrong D:') }); render( <PanelContextProvider> <AgentInformationPanel /> </PanelContextProvider> ); // 触发面板渲染 const { result } = renderHook(() => useContext(PanelContext), { wrapper: PanelContextProvider }); result.current.setRenderPanel(true); // 断言错误消息存在 const errorElement = await screen.findByText('Error: Something went wrong D:'); expect(errorElement).toBeInTheDocument(); });
补充说明
若你仍想使用直接模拟Context的方式,需将模拟的error改为Error实例,而非字符串:
const rejectContext = { agent: null, loading: true, error: new Error('Something went wrong! D:'), // 改为Error实例 renderPanel: true };
内容的提问来源于stack exchange,提问作者Kosh
相关产品推荐
相关产品推荐

