如何用JEST+React Testing Library测试自定义Filter组件及各字段功能
React Filter 组件 Jest + React Testing Library 测试方案
前置依赖确认
确保项目已安装以下测试依赖:
@testing-library/reactv14+@testing-library/jest-dom@testing-library/user-eventv14+jestv28+
以下测试用例基于Filter组件常规props逻辑编写,你可以根据实际组件的入参配置调整对应参数。
核心测试场景覆盖
1. 基础渲染校验
- 所有配置的字段(文本框、下拉框、日期选择器等)按预期渲染
- 字段标签、占位符、默认值与配置一致
2. 交互逻辑校验
- 各类型字段输入/选择后值实时同步
- 重置、查询按钮点击后对应逻辑正常触发
3. 格式规则校验
- 邮箱、手机号等特殊字段非法格式触发对应错误提示
- 必填字段空值提交触发必填校验
可运行测试代码示例
Filter 组件完整测试代码
import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import Filter from './Filter'; // 替换为你实际的Filter组件配置 const mockFilterConfig = [ { type: 'text', name: 'username', label: '用户名', placeholder: '请输入用户名' }, { type: 'email', name: 'email', label: '邮箱', placeholder: '请输入绑定邮箱', validation: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val) ? '' : '邮箱格式不正确' }, { type: 'select', name: 'role', label: '用户角色', options: [ { label: '超级管理员', value: 'super_admin' }, { label: '普通用户', value: 'general_user' } ] } ]; describe('Filter 组件全场景测试', () => { const user = userEvent.setup(); // 基础渲染测试 test('所有配置字段正常渲染', () => { render(<Filter config={mockFilterConfig} />); // 校验用户名文本框存在 expect(screen.getByRole('textbox', { name: /用户名/ })).toBeInTheDocument(); // 校验邮箱文本框存在 expect(screen.getByRole('textbox', { name: /邮箱/ })).toBeInTheDocument(); // 校验角色下拉框存在 expect(screen.getByRole('combobox', { name: /用户角色/ })).toBeInTheDocument(); }); // 文本框输入交互测试 test('文本框输入内容正常同步', async () => { render(<Filter config={mockFilterConfig} />); const usernameInput = screen.getByRole('textbox', { name: /用户名/ }); await user.type(usernameInput, 'test001'); expect(usernameInput).toHaveValue('test001'); }); // 邮箱格式校验测试 test('邮箱字段非法格式触发错误提示', async () => { render(<Filter config={mockFilterConfig} />); const emailInput = screen.getByRole('textbox', { name: /邮箱/ }); // 输入非法邮箱触发失焦校验 await user.type(emailInput, 'test-wrong-format'); await user.tab(); await waitFor(() => { expect(screen.getByText('邮箱格式不正确')).toBeInTheDocument(); }); // 输入合法邮箱后错误提示消失 await user.clear(emailInput); await user.type(emailInput, 'test@example.com'); await user.tab(); await waitFor(() => { expect(screen.queryByText('邮箱格式不正确')).not.toBeInTheDocument(); }); }); // 下拉框选择交互测试 test('下拉框选项选择后值正常更新', async () => { render(<Filter config={mockFilterConfig} />); const roleSelect = screen.getByRole('combobox', { name: /用户角色/ }); await user.selectOptions(roleSelect, 'super_admin'); expect(roleSelect).toHaveValue('super_admin'); }); // 重置功能测试 test('点击重置按钮后所有字段值清空', async () => { const mockResetCallback = jest.fn(); render(<Filter config={mockFilterConfig} onReset={mockResetCallback} />); // 先填充字段内容 await user.type(screen.getByRole('textbox', { name: /用户名/ }), 'test001'); await user.selectOptions(screen.getByRole('combobox', { name: /用户角色/ }), 'super_admin'); // 点击重置 const resetBtn = screen.getByRole('button', { name: /重置/ }); await user.click(resetBtn); // 校验字段清空、回调触发 expect(screen.getByRole('textbox', { name: /用户名/ })).toHaveValue(''); expect(screen.getByRole('combobox', { name: /用户角色/ })).toHaveValue(''); expect(mockResetCallback).toHaveBeenCalled(); }); });
RenderTextBox 单独测试代码
import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import RenderTextBox from './RenderTextBox'; test('RenderTextBox 邮箱校验逻辑正常运行', async () => { const mockChangeCallback = jest.fn(); const user = userEvent.setup(); render( <RenderTextBox label="邮箱" name="email" validation={(val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val) ? '' : '格式错误'} onChange={mockChangeCallback} /> ); const input = screen.getByRole('textbox', { name: /邮箱/ }); await user.type(input, 'wrong-format'); await user.tab(); await waitFor(() => { expect(screen.getByText('格式错误')).toBeInTheDocument(); }); expect(mockChangeCallback).toHaveBeenCalledWith('wrong-format'); });
断言逻辑说明
- 元素存在校验优先使用
getBy*系列API配合toBeInTheDocument(),元素不存在校验使用queryBy*系列API - 输入/选择后的值校验使用
toHaveValue(),回调触发校验使用jest mock函数配合toHaveBeenCalled()/toHaveBeenCalledWith() - 异步场景(错误提示延迟展示、接口联动过滤)使用
waitFor包裹断言,等待状态更新完成后再做校验
内容的提问来源于stack exchange,提问作者Arslaan Muhammad Ali
相关产品推荐
相关产品推荐

