01. 为什么需要测试
写代码就像搭积木,你搭好了积木要验收对不对。测试就是验收环节,帮你自动检查代码有没有按预期运行。React 组件测试跟前端自动点击页面很像,只不过是用代码来模拟用户操作。没测试的代码就像没有说明书的电器,出了毛病你都不知道从哪里修起。
javascript
import { render, screen } from '@testing-library/react'
import App from './App'
test('renders hello', () => {
render(<App />)
const el = screen.getByText(/hello/i)
expect(el).toBeInTheDocument()
})写测试不要追求覆盖率数字,要追求有价值的用例。
02. 安装和配置测试环境
Create React App 自带 Jest 和 Testing Library,不需要额外装。如果是手动搭的 Vite 项目,需要自己装 vitest 或 jest。关键是要配好 jsdom 环境,因为测试是在 Node 里跑的,没有真实的浏览器 DOM,jsdom 帮我们模拟了一个浏览器环境。
bash
npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom
# 或者用 jest
npm install -D jest @testing-library/react @testing-library/jest-domvitest 比 jest 快很多,新项目推荐用 vitest。
03. 查询 DOM 元素的各种姿势
Testing Library 提供了一堆查询方法,按优先级排列:getByRole 最推荐,因为最贴近无障碍体验。然后是 getByLabelText、getByPlaceholderText、getByText、getByTestId。getBy 找不到元素会直接抛异常,queryBy 找不到返回 null,findBy 是异步的等待元素出现。
javascript
const btn = screen.getByRole('button', { name: /提交/i })
const input = screen.getByLabelText(/用户名/i)
const title = screen.getByText(/欢迎回来/)
const list = await screen.findByRole('list')尽量少用 getByTestId,这个东西跟实现细节耦合太紧。
04. 模拟用户交互
用 fireEvent 或 userEvent 来模拟用户操作。userEvent 比 fireEvent 更接近真实用户行为,比如 userEvent.type 会触发 keyDown、keyPress、keyUp 等一系列事件,而 fireEvent 只触发你指定的那一个。推荐优先用 userEvent。
javascript
import userEvent from '@testing-library/user-event'
test('user can type and submit', async () => {
const user = userEvent.setup()
render(<LoginForm />)
await user.type(screen.getByLabelText(/邮箱/), '[email protected]')
await user.click(screen.getByRole('button', { name: /登录/ }))
await waitFor(() => expect(mockLogin).toHaveBeenCalled())
})05. Mock 和异步测试
Mock 就是造假数据糊弄测试。比如你组件里调了 fetch,在测试里不可能真的发请求,就得用 jest.fn() 伪造一个假的 fetch 函数。异步测试要注意用 waitFor 或 findBy 等待断言,不然测试跑完了 Promise 还没 resolve 就炸了。
javascript
global.fetch = jest.fn(() =>
Promise.resolve({ json: () => Promise.resolve({ name: '小明' }) })
)
test('loads user name', async () => {
render(<UserCard id={1} />)
await waitFor(() => {
expect(screen.getByText('小明')).toBeInTheDocument()
})
})Mock 用多了会让测试失去意义,尽量少 mock 核心业务逻辑。
知识测验
第 1/5 题正确 0
React Testing Library 中最推荐的查询方法是什么?