ReactJS 测试:初学者指南

你好,未来的React开发者们!我很高兴能成为你们在这React测试世界之旅的向导。作为一个教计算机科学多年的老师,我亲眼见证了测试如何将一个好的开发者转变为一个伟大的开发者。那么,让我们一起来揭开React测试的神秘面纱吧!

ReactJS - Testing

测试的重要性

在我们开始编码之前,让我先分享一个小故事。我曾经有一个学生,他构建了一个漂亮的React应用。它看起来完美……直到在演示时崩溃。那时他痛苦地认识到:外观可能会欺骗人,但测试不会。测试不仅仅是为了捕捉错误;它是关于信心。当你的测试通过时,你可以安心入睡,知道你的代码按预期工作。

Create React App:你的测试游乐场

设置你的环境

让我们从使用Create React App创建一个新的React应用开始。这个工具会设置一个已经配置好测试的Ready-to-go React项目。打开你的终端并输入:

npx create-react-app my-react-testing-app
cd my-react-testing-app

恭喜你!你刚刚创建了一个带有内置测试功能的第一个React应用。就像得到了一个装满电池的新玩具!

你的第一个测试

Create React App带有一个示例测试文件。让我们来看看它。打开src/App.test.js

import { render, screen } from '@testing-library/react';
import App from './App';

test('渲染了学习React的链接', () => {
render(<App />);
const linkElement = screen.getByText(/学习 react/i);
expect(linkElement).toBeInTheDocument();
});

让我们分解一下:

  1. 我们导入了必要的测试工具和我们的App组件。
  2. 我们使用test函数定义了一个测试。
  3. 我们渲染了我们的App组件。
  4. 我们寻找包含文本"学习React"的元素。
  5. 我们期望这个元素在文档中。

要运行这个测试,使用命令:

npm test

如果一切设置正确,你应该会看到一个通过的测试。恭喜你完成第一个React测试!

在自定义应用中测试

现在我们已经看到了一个基本的测试,让我们创建我们自己的组件并测试它。

创建一个简单的组件

让我们创建一个简单的计数器组件。创建一个新文件src/Counter.js

import React, { useState } from 'react';

function Counter() {
const [count, setCount] = useState(0);

return (
<div>
<p>计数:{count}</p>
<button onClick={() => setCount(count + 1)}>增加</button>
</div>
);
}

export default Counter;

这个组件显示一个计数和一个按钮来增加它。

为我们的计数器编写测试

现在,让我们测试我们的Counter组件。创建一个新文件src/Counter.test.js

import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test('初始计数渲染为0', () => {
render(<Counter />);
const countElement = screen.getByText(/计数: 0/i);
expect(countElement).toBeInTheDocument();
});

test('点击按钮时计数增加', () => {
render(<Counter />);
const button = screen.getByText(/增加/i);
fireEvent.click(button);
const countElement = screen.getByText(/计数: 1/i);
expect(countElement).toBeInTheDocument();
});

让我们分解这些测试:

  1. 第一个测试检查初始计数是否为0。
  2. 第二个测试模拟按钮点击并检查计数是否增加到1。

再次运行npm test,你应该会看到这些新测试通过!

高级测试概念

当你对基本测试感到舒适时,你会想要探索更高级的概念。下面是一些你在React测试中通常会用到的方法表格:

方法 描述 示例
render 渲染一个React组件用于测试 render(<MyComponent />)
screen.getByText 通过文本内容查找元素 screen.getByText(/你好世界/i)
screen.getByRole 通过ARIA角色查找元素 screen.getByRole('button')
fireEvent 模拟DOM事件 fireEvent.click(button)
waitFor 等待期望通过 await waitFor(() => expect(element).toBeVisible())
act 包裹导致React状态更新的代码 act(() => { /* 执行操作 */ })

测试异步行为

React应用程序通常涉及异步操作。让我们创建一个获取数据的组件并测试它:

// UserData.js
import React, { useState, useEffect } from 'react';

function UserData() {
const [userData, setUserData] = useState(null);

useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => response.json())
.then(data => setUserData(data));
}, []);

if (!userData) return <div>加载中...</div>;

return <div>用户名:{userData.name}</div>;
}

export default UserData;

现在,让我们测试这个组件:

// UserData.test.js
import { render, screen, waitFor } from '@testing-library/react';
import UserData from './UserData';

test('加载并显示用户数据', async () => {
render(<UserData />);

expect(screen.getByText(/加载中/i)).toBeInTheDocument();

await waitFor(() => {
expect(screen.getByText(/用户名:/i)).toBeInTheDocument();
});
});

这个测试检查加载状态,然后等待用户数据被显示。

结论

React中的测试一开始可能看起来很吓人,但它是一个宝贵的技能,会让你成为一个更好的开发者。记住,你写的每一个测试都是你代码的安全网。它在你跌倒时抓住你,并给你信心去攀登更高。

在你继续React之旅时,继续探索不同的测试技术。模拟API调用,测试错误状态,挑战自己在编写组件之前先写测试(测试驱动开发)。你练习得越多,它就会变得越自然。

快乐测试,愿你的控制台总是因为通过的测试而显示绿色!

Credits: Image by storyset