2021-04-14 19:02:59
使用 Jest 和 React 测试库(RTL)测试 React 应用程序是当前主流的测试方案,其核心在于通过模拟用户行为验证组件功能,同时遵循可访问性和非实现细节测试的最佳实践。
一、核心工具与优势Jest
提供断言库、测试运行器、Mock 功能及覆盖率报告,支持异步测试和快照测试。
优势:开箱即用的配置、丰富的 API、活跃的社区支持。
React Testing Library (RTL)
基于 DOM 测试,鼓励通过用户视角(如文本、角色、标签)而非组件实现细节(如状态、实例方法)进行测试。
优势:与 React 生态深度集成,测试代码更贴近真实用户场景,减少维护成本。

核心原则
避免测试组件内部状态或方法,聚焦用户可见的行为(如按钮点击、输入变化、页面渲染)。
通过 screen.getByRole、screen.getByText 等查询方法定位元素,而非 data-testid(仅在必要时使用)。
示例代码
test('点击按钮后文本更新', () => { render(<Counter />); fireEvent.click(screen.getByRole('button', { name: /增加/i })); expect(screen.getByText('计数: 1')).toBeInTheDocument();});异步操作测试
使用 waitFor 或 async/await 处理异步更新(如 API 调用、定时器)。
示例:模拟 API 响应并验证渲染结果。
test('加载数据后显示列表', async () => { const mockData = [{ id: 1, name: 'Test' }]; server.use(rest.get('/api/data', (req, res, ctx) => { return res(ctx.json(mockData)); })); render(<DataFetcher />); await waitFor(() => expect(screen.getByText('Test')).toBeInTheDocument());});上下文与钩子测试
使用 MemoryRouter、ThemeProvider 等包装组件以模拟上下文环境。
示例:测试主题切换功能。
test('切换主题后样式变化', () => { render( <ThemeProvider theme={darkTheme}> <ThemeToggle /> </ThemeProvider> ); fireEvent.click(screen.getByLabelText('切换主题')); expect(screen.getByTestId('app')).toHaveStyle({ background: '#333' });});错误处理测试
模拟错误边界或 API 失败场景,验证错误提示的显示。
示例:测试表单提交失败时的提示。
test('提交失败时显示错误信息', async () => { server.use(rest.post('/api/submit', (req, res, ctx) => { return res(ctx.status(500)); })); render(<Form />); fireEvent.submit(screen.getByRole('form')); await waitFor(() => expect(screen.getByText('提交失败')).toBeInTheDocument());});元素未找到错误
原因:查询条件不匹配或元素未渲染。
解决:使用 debug() 打印 DOM 结构,检查查询参数(如 exact: false 允许部分匹配)。
异步测试超时
原因:未正确等待异步操作完成。
解决:增加 waitFor 超时时间或优化模拟数据返回速度。
Mock 泄漏
原因:测试间 Mock 未清理,导致数据污染。
解决:在 afterEach 中调用 jest.clearAllMocks() 或使用 MSW 的 server.resetHandlers()。
测试分层
单元测试:隔离测试组件逻辑(如自定义钩子)。
集成测试:测试组件间交互(如父子组件通信)。
E2E 测试:使用 Cypress 或 Playwright 验证完整流程。
可访问性优先
通过 role、label 等属性定位元素,确保测试代码同时验证 A11Y 属性。
测试命名规范
使用 describe 分组相关测试,命名格式为 组件名/场景: 预期行为(如 Counter/increment: updates count by 1)。
性能优化
使用 jest.mock 模拟重型依赖(如 axios),避免测试运行缓慢。
通过 --watch 模式仅运行相关测试文件,提升开发效率。
课程与文档
工具链
Mock Service Worker (MSW):模拟 API 请求,支持拦截浏览器和服务端请求。
User Event:模拟更真实的用户输入(如拖拽、复制粘贴)。
通过结合 Jest 的强大功能与 RTL 的用户中心设计理念,开发者可以构建出健壮、易维护的 React 测试套件,显著提升代码质量和开发信心。