# 使用 Jest + React Testing Library 编写测试

URL: https://caijiao.org/react/chapter15/testing
Source: docs/react/chapter15/testing.md
Description: 使用 Jest 和 React Testing Library 编写测试是确保 React 应用质量和稳定性的重要方式。本文将介绍如何配置和使用 Jest 以及 React Testing Library 编写组件测试。

Jest 和 React Testing Library 是当前 React 开发中最常用的测试工具。Jest 是一个 JavaScript 测试框架，适用于单元测试、集成测试和端到端测试。而 React Testing Library 提供了一些工具和方法，使得编写 React 组件的测试变得更加简单和直观。结合使用这两者，可以有效地测试 React 应用的各个方面。

## 安装和配置

首先，您需要在项目中安装 Jest 和 React Testing Library。

### 安装 Jest

如果您的 React 应用是通过 Create React App 创建的，Jest 已经内置在其中。否则，您可以手动安装 Jest。

```bash
npm install --save-dev jest
````

### 安装 React Testing Library

React Testing Library 可以通过 npm 安装。

```bash
npm install --save-dev @testing-library/react @testing-library/jest-dom
```

## 编写测试

### 创建组件

假设我们有一个简单的 `Button` 组件，接收一个 `label` 属性并渲染一个按钮。

```javascript
// Button.js
import React from 'react';

const Button = ({ label, onClick }) => {
  return <button onClick={onClick}>{label}</button>;
};

export default Button;
```

### 编写测试

接下来，我们为该组件编写一个测试。使用 React Testing Library，我们可以通过查询 DOM 元素，模拟用户操作和断言结果。

```javascript
// Button.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

test('renders Button with label', () => {
  render();

  // 查找按钮并断言其文本内容
  const buttonElement = screen.getByText(/click me/i);
  expect(buttonElement).toBeInTheDocument();
});

test('calls onClick when clicked', () => {
  const mockOnClick = jest.fn();

  render();

  // 查找按钮并模拟点击
  const buttonElement = screen.getByText(/click me/i);
  fireEvent.click(buttonElement);

  // 断言 onClick 被调用
  expect(mockOnClick).toHaveBeenCalledTimes(1);
});
```

### 测试解释

1. **render**: 这个方法会将组件渲染到虚拟 DOM 中，为测试提供所需的元素。
2. **screen**: React Testing Library 提供的全局对象，用于查询渲染后的 DOM 元素。`screen.getByText()` 用于查找包含特定文本的元素。
3. **fireEvent**: 模拟用户事件，例如点击按钮。`fireEvent.click()` 用于模拟点击事件。
4. **jest.fn()**: 创建一个模拟函数，用来监听组件的回调函数（如 `onClick`）是否被正确调用。

### 运行测试

在项目根目录下运行以下命令来执行测试：

```bash
npm test
```

Jest 会自动搜索所有的测试文件并执行。

## 常见的测试方法

### 查询元素

* `screen.getByText()`：根据文本查找元素。
* `screen.getByRole()`：根据角色查找元素（例如按钮、链接等）。
* `screen.getByLabelText()`：根据元素的标签文本查找。
* `screen.getByPlaceholderText()`：根据输入框的占位符文本查找。
* `screen.getByTestId()`：根据 `data-testid` 属性查找元素。

### 模拟用户事件

* `fireEvent.click()`：模拟点击事件。
* `fireEvent.change()`：模拟输入框值的变化。
* `fireEvent.submit()`：模拟表单提交。

### 断言

* `expect(element).toBeInTheDocument()`：断言元素在文档中存在。
* `expect(element).toHaveTextContent(text)`：断言元素的文本内容。
* `expect(mockFunction).toHaveBeenCalledTimes(count)`：断言模拟函数被调用的次数。

## 总结

Jest 和 React Testing Library 是 React 测试中不可或缺的工具。Jest 提供了强大的测试框架，而 React Testing Library 使得测试组件的渲染和用户交互变得简单直观。通过合理使用这两个工具，您可以确保 React 应用在开发过程中保持高质量和高稳定性。
