标准答案
- Testing Library 鼓励从用户视角测试组件,不直接依赖组件实例、内部 state 或私有方法。
- 查询元素时优先使用 getByRole、getByLabelText、getByText 等接近可访问语义的方式。
- 交互应使用 userEvent 模拟真实用户输入、点击、键盘操作,而不是只触发底层事件。
- 断言重点应该是页面结果、可见文本、按钮状态、表单错误、回调是否按用户行为触发。
- 它适合组件行为测试,不适合替代单元测试、E2E 测试或性能测试。
题目解析
这道题的重点是测试理念,而不是 API 名称。Testing Library 反对围绕实现细节写脆弱测试。
按 role 和 label 查询也会倒逼组件具备更好的可访问性。如果按钮没有可访问名称,测试不好写,用户也可能不好用。
组件重构时,只要用户行为和页面输出不变,Testing Library 风格的测试通常更稳定。
代码示例
下面的测试验证用户点击提交后看到了错误提示,而不是检查组件内部 state。
TSX
it('shows validation message when name is empty', async () => {
render(<UserForm />)
await userEvent.click(screen.getByRole('button', { name: '提交' }))
expect(screen.getByText('请输入姓名')).toBeInTheDocument()
})常见误区
- 用 className、DOM 层级或测试 id 作为首选查询方式,测试和实现结构强耦合。
- 只测组件内部函数是否被调用,没有验证用户能看到的结果。
- 把 Testing Library 当作 E2E 工具,试图覆盖完整跨页面业务链路。