测试依赖自定义useFetch Hook的React组件渲染失败问题
问题:测试AgentsContainer组件时无法找到agent-card元素
我在测试依赖自定义useFetch Hook的AgentsContainer组件,验证它是否能正确渲染所有Agent卡片,但测试时出现无法找到data-testid='agent-card'元素的错误。另外,移除agents后的可选链操作符(?)会抛出"TypeError: Cannot read properties of undefined (reading 'map')"错误。
AgentsContainer.js
import React from 'react'; import { useFetch } from '../../hooks/useFetch.js'; import AgentBox from './AgentBox/AgentBox.js'; function AgentsContainer() { const { agents, loading, error } = useFetch( 'https://valorant-api.com/v1/agents' ); return ( <section> <div> {error && <div>Error: {error.message}</div>} {loading && <div>Loading...</div>} {agents?.map(agent => { return ( agent.isPlayableCharacter && ( <AgentBox key={agent.uuid} data-testid='agent-card' {...agent} /> ) ); })} </div> </section> ); } export default AgentsContainer;
useFetch.js
import { useState, useEffect } from 'react'; import axios from 'axios'; export function useFetch(url) { const [agents, setAgents] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(); useEffect(() => { setLoading(true); axios .get(url) .then(({ data: { data } }) => { setAgents(data); }) .catch(error => setError(error)) .finally(() => setLoading(false)); }, []); return { agents, loading, error }; }
AgentsContainer.test.js
import React from 'react'; import { render, screen } from '@testing-library/react'; import AgentsContainer from './AgentsContainer.js'; import agentsMock from '../../mock/mock.js'; import axios from 'axios'; jest.mock('axios'); test('Renders Agents cards', async () => { axios.get.mockResolvedValue({ data: agentsMock, loading: true, error: 'Something went wrong D:' }); render(<AgentsContainer />); const agentsCards = await screen.findAllByTestId('agent-card'); expect(agentsCards).toHaveLength(3); });
控制台报错信息
Unable to find an element by: [data-testid="agent-card"] Ignored nodes: comments, script, style <body> <div> <section> <div /> </section> </div> </body> 16 | render(<AgentsContainer />); 17 | > 18 | const agentsCards = await screen.findAllByTestId('agent-card'); | ^ 19 | 20 | expect(agentsCards).toHaveLength(3); 21 | });
注:测试中导入的agentsMock是包含3个对象的数组,数据量较大未贴出,需要可提供。
解决方案
1. 修复Axios Mock的返回结构
useFetch中对Axios响应的处理是({ data: { data } }),意味着它期望响应结构为{ data: { data: 代理数组 } },但当前测试的mock直接返回了{ data: agentsMock },导致setAgents(data)接收到的内容不符合预期,无法生成Agent卡片。
修正后的mock代码:
axios.get.mockResolvedValue({ data: { data: agentsMock // 匹配useFetch的解构层级 } });
2. 确保Mock数据满足渲染条件
AgentsContainer仅在agent.isPlayableCharacter为true时才渲染AgentBox,因此agentsMock中的每个对象必须包含isPlayableCharacter: true字段,否则不会生成对应的卡片元素。
3. 修正可选链报错问题
移除agents?.map的可选链后报错,本质是mock结构错误导致agents被设置为undefined。修复mock结构后,useFetch初始的agents状态为数组,不会出现读取map的报错。
修正后的完整测试代码
import React from 'react'; import { render, screen } from '@testing-library/react'; import AgentsContainer from './AgentsContainer.js'; import agentsMock from '../../mock/mock.js'; import axios from 'axios'; jest.mock('axios'); test('Renders Agents cards', async () => { axios.get.mockResolvedValue({ data: { data: agentsMock } }); render(<AgentsContainer />); // 可额外验证loading状态的切换 await screen.findByText(/Loading.../i); const agentsCards = await screen.findAllByTestId('agent-card'); expect(agentsCards).toHaveLength(3); });
额外检查点
- 确认
AgentBox组件正确接收并保留了data-testid属性,未被内部逻辑覆盖或丢失 - 检查
agentsMock中的每个对象是否包含uuid(作为React元素的key)和isPlayableCharacter: true字段
内容的提问来源于stack exchange,提问作者Kosh
相关产品推荐
相关产品推荐

