如何使用Jest/React Testing Library测试带onClick的React组件
测试实现方案
你当前写的const btn = screen.getByRole('button', {name: '1 hour'});放在测试用例外部,会在组件还未渲染时就执行DOM查询,直接导致查询失败,所有DOM查询操作都需要放在组件渲染完成后的用例内部执行。
你要覆盖onClick的两行逻辑,只需要分别验证回调函数执行情况、激活状态更新结果即可,不需要直接mock组件内部的setActiveIdx:
- 回调函数
inner.cb通过jest模拟即可验证执行次数和传参 - 状态更新的结果可以通过按钮激活后的UI特征(比如激活类名、aria属性等)验证
1. 前置准备
首先构造带mock回调的测试用数据:
// 用jest.fn生成模拟回调函数 const mockCallback = jest.fn(); // 测试用数据源,和你实际业务数据结构保持一致即可 const TestData = [ { id: 1, title: '1 hour', cb: mockCallback }, { id: 2, title: '2 hour', cb: mockCallback } ];
2. 完整测试用例
import { render, screen, fireEvent } from '@testing-library/react'; import ButtonGroup from './你的组件路径'; describe('ButtonGroup 组件', () => { // 每个测试用例执行前重置mock状态,避免用例之间互相影响 beforeEach(() => { jest.clearAllMocks(); }); it('正常渲染不崩溃', () => { const { container } = render(<ButtonGroup data={TestData}/>); expect(container).toBeInTheDocument(); }); it('点击按钮后回调正确触发、激活状态正常更新', () => { render(<ButtonGroup data={TestData}/>); // 在组件渲染完成后再查询目标按钮 const targetBtn = screen.getByRole('button', { name: '1 hour' }); // 触发点击事件 fireEvent.click(targetBtn); // 校验回调执行情况:执行1次,传参为当前按钮的index(第一个按钮index为0) expect(mockCallback).toBeCalledTimes(1); expect(mockCallback).toBeCalledWith(0); // 校验激活状态:替换为你组件实际的激活标识即可 // 比如激活后有active类名,或者有aria-pressed="true"属性 expect(targetBtn).toHaveClass('active'); }); });
补充优化建议
你组件里的按钮data-testid存在语法错误,少了闭合引号,建议修改为带index区分每个按钮唯一的testid,方便测试查询:
<button type="button" data-testid={`btn-test-${index}`} onClick={() => {setActiveIdx(() => index); inner.cb(index)}} key={inner.id} > {inner.title} </button>
修改后你也可以通过testid查询按钮,不用依赖按钮文案:
const targetBtn = screen.getByTestId('btn-test-0');
内容的提问来源于stack exchange,提问作者Sole
相关产品推荐
相关产品推荐

