如何在useEffect钩子中模拟来自自定义hook的fetchData请求
如何模拟useEffect中的fetchData调用?
我正在测试一个组件,该组件通过useEffect调用自定义hook的fetchData函数获取数据,组件核心代码如下:
useEffect(() => { const getCharacter = async () => { try { const response = await fetchData( `${REACT_APP_BASE_API_URL}/characters/${characterId}?apikey=${REACT_APP_API_PUBLIC_KEY3}` ); const character = response.results[0]; setCharacter(character); } catch (error) { navigate('*'); } }; getCharacter(); }, [characterId, navigate, fetchData]);
对应的测试代码如下:
test('Should render the character',()=>{ render(<CharacterDetails/>) await waitFor(()=>{ expect(getByText('exampleName')).toBeInTheDocument() }) })
测试过程中fetch始终返回null,页面无法渲染数据,以下是两种可行的模拟方案:
方案一:直接模拟自定义hook的fetchData函数
如果fetchData是从某个自定义hook导出的工具函数,用Jest的mock机制直接替换它:
// 导入目标函数并模拟 import { fetchData } from '../path-to-your-custom-hook'; jest.mock('../path-to-your-custom-hook', () => ({ fetchData: jest.fn() })); test('Should render the character', async () => { // 构造模拟返回的成功数据 const mockResponse = { results: [{ name: 'exampleName' }] }; // 让fetchData返回模拟数据 fetchData.mockResolvedValue(mockResponse); render(<CharacterDetails />); await waitFor(() => { expect(getByText('exampleName')).toBeInTheDocument(); }); // 可选:验证fetchData是否按预期被调用 expect(fetchData).toHaveBeenCalled(); });
方案二:模拟全局fetch(如果fetchData基于原生fetch实现)
如果fetchData内部调用了浏览器原生的fetch API,可以直接全局模拟fetch:
test('Should render the character', async () => { // 全局替换fetch,返回预设的模拟数据 global.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve({ results: [{ name: 'exampleName' }] }) }) ); render(<CharacterDetails />); await waitFor(() => { expect(getByText('exampleName')).toBeInTheDocument(); }); // 可选:验证fetch的调用URL是否符合预期 expect(fetch).toHaveBeenCalledWith( expect.stringContaining('/characters/') ); });
注意:原测试代码中的getByeText是拼写错误,正确应为getByText,已在示例中修正。
内容的提问来源于stack exchange,提问作者ludinj
相关产品推荐
相关产品推荐

