測試 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
中導入 render
和 fireEvent
,兩個輔助工具。第一個可以讓我們渲染 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 元件,傳遞 1
給 increment
,並將我們的 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”]