/

測試 React 元件

測試 React 元件

使用 Jest 和 react-testing-library 測試你的第一個 React 元件

開始測試 React 元件最簡單的方法是使用快照測試。快照測試是一種讓你在獨立環境中測試元件的技術。

如果你對軟體測試很熟悉,這就像你為類別進行單元測試一樣:你測試每個元件的功能。

我假設你已經使用 create-react-app 創建了一個 React 應用,這個應用已經預先安裝了我們需要的測試套件 Jest

讓我們從一個簡單的測試開始。CodeSandbox 是一個很好的環境來嘗試這個。在 CodeSandbox 中創建一個 React sandbox,並在 components 文件夾中創建一個 App.js 元件,然後添加一個 App.test.js 文件。

1
2
3
4
5
6
7
8
9
10
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>
)
}

我們的第一個測試很簡單:

1
2
3
test('First test', () => {
expect(true).toBeTruthy()
})

當 CodeSandbox 檢測到測試文件時,它會自動執行這些測試,你可以點擊視圖底部的 “Tests” 按鈕來查看測試結果:

一個測試文件可以包含多個測試:

現在讓我們做一些更有用的事情,實際上測試一個 React 元件。我們現在只有一個沒有實際用途的 App 元件,所以讓我們先設置一個具有更多功能的小應用程式環境:我們之前構建的計數器應用程式。如果你跳過了這部分,你可以返回並閱讀我們是如何構建它的,但為了方便參考,我在這裡再次添加一遍。

它僅由兩個元件組成:App 和 Button。創建 App.js 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 文件:

1
2
3
4
5
6
7
8
9
10
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 中導入 renderfireEvent,兩個輔助工具。第一個可以讓我們渲染 JSX,第二個可以讓我們釋放組件上的事件。

在與 Button.js 相同的文件夾中創建一個 Button.test.js 文件。

1
2
3
import React from 'react'
import { render, fireEvent } from 'react-testing-library'
import Button from './Button'

按鈕在應用程式中用於接受點擊事件,然後它們會調用傳遞給 onClickFunction 屬性的函數。我們添加了一個 count 變量,然後創建一個將它增加的函數:

1
2
3
4
5
let count

const incrementCount = increment => {
count += increment
}

現在是進行實際測試的時候。我們首先將 count 初始化為 0,然後渲染一個 +1 的 Button 元件,傳遞 1increment,並將我們的 incrementCount 函數傳遞給 onClickFunction

接著我們獲取元件的第一個子元素的內容,並檢查它輸出 +1

然後我們點擊按鈕,並檢查 count 從 0 變成 1:

1
2
3
4
5
6
7
8
9
10
11
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:

1
2
3
4
5
6
7
8
9
10
11
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 個按鈕和頁面上的結果。我們可以檢查每個按鈕,看看結果在點擊它們時是否增加,也可以點擊多次:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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

tags: [“react”, “testing”, “jest”, “react-testing-library”]