使用 Jest 和 react-testing-library
測試你的第一個 React 元件
開始測試 React 元件最簡單的方法是使用快照測試。快照測試是一種讓你在獨立環境中測試元件的技術。
如果你對軟體測試很熟悉,這就像你為類別進行單元測試一樣:你測試每個元件的功能。
我假設你已經使用 create-react-app
創建了一個 React 應用,這個應用已經預先安裝了我們需要的測試套件 Jest。
讓我們從一個簡單的測試開始。CodeSandbox 是一個很好的環境來嘗試這個。在 CodeSandbox 中創建一個 React sandbox,並在 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 檢測到測試文件時,它會自動執行這些測試,你可以點擊視圖底部的 “Tests” 按鈕來查看測試結果:
一個測試文件可以包含多個測試:
現在讓我們做一些更有用的事情,實際上測試一個 React 元件。我們現在只有一個沒有實際用途的 App 元件,所以讓我們先設置一個具有更多功能的小應用程式環境:我們之前構建的計數器應用程式。如果你跳過了這部分,你可以返回並閱讀我們是如何構建它的,但為了方便參考,我在這裡再次添加一遍。
它僅由兩個元件組成:App 和 Button。創建 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
,這是一個很好的幫助工具,它可以讓我們檢查每個元件的輸出並對其應用事件。你可以在 這裡 了解更多相關信息,或觀看 這個視頻。
讓我們先測試 Button 元件。
我們首先從 react-testing-library
中導入 render
和 fireEvent
,兩個輔助工具。第一個可以讓我們渲染 JSX,第二個可以讓我們釋放組件上的事件。
在與 Button.js
相同的文件夾中創建一個 Button.test.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
。
然後我們點擊按鈕,並檢查 count 從 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
,並且通過按鈕點擊將 count 增加了 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