# 单元测试与组件测试

URL: https://caijiao.org/react/chapter15/unit-testing
Source: docs/react/chapter15/unit-testing.md
Description: 单元测试和组件测试是确保 React 应用稳定性和功能性的重要方法。单元测试关注单个函数或模块，而组件测试侧重于验证 React 组件的行为和交互。本文将深入探讨这两种测试方法。

在 React 开发中，测试是保证代码质量的重要环节。测试方法可以分为单元测试和组件测试，这两者有不同的侧重点和应用场景。单元测试侧重于测试单一函数或模块的功能，而组件测试则更关注 React 组件的行为和与用户的交互。通过这两种测试方法的结合，开发者可以有效提高应用的稳定性和可靠性。

## 单元测试

单元测试是对代码中最小的功能单元进行测试，通常是测试单个函数、方法或模块。其主要目标是验证代码中的每个函数或模块是否按预期工作，特别是在不同的输入下，是否能够产生正确的输出。

### 示例：单元测试函数

假设我们有一个简单的计算函数 `sum`，它返回两个数字的和：

```javascript
// sum.js
export const sum = (a, b) => a + b;
````

我们可以为 `sum` 函数编写一个单元测试来确保其行为正确：

```javascript
// sum.test.js
import { sum } from './sum';

test('adds two numbers', () => {
  expect(sum(1, 2)).toBe(3);
  expect(sum(-1, -2)).toBe(-3);
  expect(sum(0, 0)).toBe(0);
});
```

在这个示例中，我们测试了 `sum` 函数的不同输入，确保其能够按预期返回正确的结果。

## 组件测试

组件测试是针对 React 组件的行为进行验证，确保组件正确渲染，并响应用户交互。React Testing Library 提供了易于使用的工具，使得我们能够以更符合用户行为的方式来测试组件，而不是仅仅测试其内部实现。

### 示例：组件测试

假设我们有一个按钮组件 `Button`，它接收 `label` 属性并且在被点击时触发一个回调函数：

```javascript
// Button.js
import React from 'react';

const Button = ({ label, onClick }) => {
  return <button onClick={onClick}>{label}</button>;
};

export default Button;
```

我们可以为该组件编写一个组件测试，检查按钮是否正确渲染，以及是否触发了回调函数：

```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);
});
```

在这个组件测试示例中，我们通过 `render` 方法将组件渲染到虚拟 DOM 中，然后通过 `screen` 查找按钮元素，并使用 `fireEvent` 模拟用户点击事件，最后通过 `expect` 断言回调函数是否被正确调用。

## 单元测试 vs 组件测试

* **单元测试**：侧重于测试单个函数、方法或模块的行为。它通常不依赖于外部依赖和 UI 渲染，目的是确保函数或模块在给定输入下能够返回正确的输出。
* **组件测试**：侧重于测试 React 组件的渲染、交互和行为。它关注的是组件如何与用户互动以及是否能正确渲染和响应事件。

## 总结

单元测试和组件测试是两种常见的测试方法，它们各自有不同的关注点和使用场景。通过结合这两种测试方法，开发者能够确保 React 应用的每个功能单元和组件都能够按预期工作，进而提升代码质量和应用稳定性。
