使用React Testing Library测试依赖接口数据的React组件点击交互
解决方案
核心思路是通过Mock接口请求解耦对真实后端的依赖,再结合测试库的异步查询、交互能力验证交互逻辑,完整实现如下:
调整后的测试代码
import axios from 'axios'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import renderer from 'react-test-renderer'; import Home from './index'; // 全局Mock axios模块 jest.mock('axios'); describe('Home', () => { // 每个测试用例执行前重置Mock、重渲染组件,避免状态串扰 beforeEach(() => { jest.clearAllMocks(); // 模拟接口返回固定测试数据 (axios.get as jest.Mock).mockResolvedValue({ data: [ { title: '测试条目1', description: '测试条目1的描述信息' }, { title: '测试条目2', description: '测试条目2的描述信息' } ] }); render(<Home />); }); it('matches snapshot', async () => { // 等待数据加载完成后再生成快照 await screen.findByText('测试条目1'); const tree = renderer.create(<Home />).toJSON(); expect(tree).toMatchSnapshot(); }); it('初始无激活项', () => { const activeItem = screen.queryByTestId('active-item'); expect(activeItem).not.toBeInTheDocument(); }); it('点击列表条目可正确设置为激活项', async () => { const user = userEvent.setup(); // 异步等待列表渲染完成 const firstItem = await screen.findByText('测试条目1'); // 触发点击 await user.click(firstItem); // 校验激活区域内容符合预期 const activeItem = screen.getByTestId('active-item'); expect(activeItem).toHaveTextContent('测试条目1'); expect(activeItem).toHaveTextContent('测试条目1的描述信息'); }); it('再次点击已激活条目可取消激活状态', async () => { const user = userEvent.setup(); const firstItem = await screen.findByText('测试条目1'); // 第一次点击激活 await user.click(firstItem); expect(screen.getByTestId('active-item')).toBeInTheDocument(); // 第二次点击取消激活 await user.click(firstItem); expect(screen.queryByTestId('active-item')).not.toBeInTheDocument(); }); });
关键逻辑说明
- 用
jest.mock('axios')模拟整个axios模块,所有调用axios.get的逻辑都会走模拟请求,不需要依赖真实后端服务,你可以根据测试需要自定义返回的data结构,覆盖空列表、异常返回等边界场景。 - 原测试代码将
render(<Home />)放在describe根作用域,只会在测试初始化时渲染一次组件,多个测试用例会共享组件实例导致状态串扰,移到beforeEach中可保证每个用例都从初始状态开始测试。 - 组件的数据拉取是异步执行的,所以需要用
findBy*系列异步查询方法等待列表渲染完成后再执行交互操作,避免查询不到元素导致测试失败。
内容的提问来源于stack exchange,提问作者Dan Zuzevich
相关产品推荐
相关产品推荐

