开始测试React组件的最简单方法是做快照测试,这是一种让你孤立地测试组件的测试技术。
如果你熟悉测试软件,这就像你为类做的单元测试:你测试每个组件的功能。
我假设你用create-react-app 创建了一个React应用,它已经安装了Jest,也就是我们需要的测试包。
让我们从一个简单的测试开始。CodeSandbox是一个很好的环境来尝试这个。从React沙盒开始,在components 文件夹中创建一个App.js 组件,并添加一个App.test.js 文件。
import React from 'react'
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
)
}
我们的第一个测试是哑巴。
test('First test', () => {
expect(true).toBeTruthy()
})
当CodeSandbox检测到测试文件时,它会自动为你运行它们,你可以点击视图底部的测试按钮来显示你的测试结果。

一个测试文件可以包含多个测试。

现在让我们做一些更有用的事情,来实际测试一个React组件。我们现在只有App,它没有做任何真正有用的事情,所以让我们先用一个具有更多功能的小应用程序来设置环境:我们之前建立的计数器应用程序。如果你跳过了它,你可以回去读一下我们是如何建立它的,但为了方便参考,我在这里再次添加它。
它只有2个组件。应用程序和按钮。创建App.js 文件。
import React, { useState } from 'react'
import Button from './Button'
const App = () => {
const [count, setCount] = useState(0)
const incrementCount = increment => {
setCount(count + increment)
}
return (
<div>
<Button increment={1} onClickFunction={incrementCount} />
<Button increment={10} onClickFunction={incrementCount} />
<Button increment={100} onClickFunction={incrementCount} />
<Button increment={1000} onClickFunction={incrementCount} />
<span>{count}</span>
</div>
)
}
export default App
和Button.js 文件。
import React from 'react'
const Button = ({ increment, onClickFunction }) => {
const handleClick = () => {
onClickFunction(increment)
}
return <button onClick={handleClick}>+{increment}</button>
}
export default Button
我们将使用react-testing-library ,它是一个很大的帮助,因为它允许我们检查每个组件的输出,并对它们应用事件。你可以在github.com/kentcdodds/…上阅读更多关于它的信息,或者通过观看这个视频。
让我们先测试一下Button组件。
react-testing-library我们首先从render 和fireEvent ,两个帮助程序。第一个让我们渲染JSX。第二个让我们在一个组件上发出事件。
创建一个Button.test.js ,并把它放在与Button.js 相同的文件夹中。
import React from 'react'
import { render, fireEvent } from 'react-testing-library'
import Button from './Button'
在应用程序中,按钮被用来接受一个点击事件,然后它们调用一个传递给onClickFunction 道具的函数。我们添加一个count 变量,并创建一个函数来增加它。
let count
const incrementCount = increment => {
count += increment
}
现在开始进行实际测试。我们首先将count初始化为0,然后我们渲染一个+1 Button 组件,将1 传给increment ,将我们的incrementCount 函数传给onClickFunction 。
然后我们得到该组件的第一个孩子的内容,并检查其输出+1 。
然后我们继续点击按钮,并检查计数是否从0到1。
test('+1 Button works', () => {
count = 0
const { container } = render(
<Button increment={1} onClickFunction={incrementCount} />
)
const button = container.firstChild
expect(button.textContent).toBe('+1')
expect(count).toBe(0)
fireEvent.click(button)
expect(count).toBe(1)
})
同样地,我们测试一个+100的按钮,这次检查输出是+100 ,并且按钮的点击使计数增加到100。
test('+100 Button works', () => {
count = 0
const { container } = render(
<Button increment={100} onClickFunction={incrementCount} />
)
const button = container.firstChild
expect(button.textContent).toBe('+100')
expect(count).toBe(0)
fireEvent.click(button)
expect(count).toBe(100)
})
现在让我们测试一下App组件。它显示了4个按钮和页面中的结果。我们可以检查每个按钮,看看当我们点击它们时,结果是否增加,点击多次也是如此。
import React from 'react'
import { render, fireEvent } from 'react-testing-library'
import App from './App'
test('App works', () => {
const { container } = render(<App />)
console.log(container)
const buttons = container.querySelectorAll('button')
expect(buttons[0].textContent).toBe('+1')
expect(buttons[1].textContent).toBe('+10')
expect(buttons[2].textContent).toBe('+100')
expect(buttons[3].textContent).toBe('+1000')
const result = container.querySelector('span')
expect(result.textContent).toBe('0')
fireEvent.click(buttons[0])
expect(result.textContent).toBe('1')
fireEvent.click(buttons[1])
expect(result.textContent).toBe('11')
fireEvent.click(buttons[2])
expect(result.textContent).toBe('111')
fireEvent.click(buttons[3])
expect(result.textContent).toBe('1111')
fireEvent.click(buttons[2])
expect(result.textContent).toBe('1211')
fireEvent.click(buttons[1])
expect(result.textContent).toBe('1221')
fireEvent.click(buttons[0])
expect(result.textContent).toBe('1222')
})
检查在这个CodeSandbox上工作的代码:https://codesandbox.io/s/pprl4y0wq