react jest測試
Testing is often seen as a tedious process. It's extra code you have to write, and in some cases, to be honest, it's not needed. But every developer should know at least the basics of testing. It increases confidence in the products they build, and for most companies, it's a requirement.
測試通常被視為乏味的過程。 這是您必須編寫的額外代碼,在某些情況下,老實說,它不是必需的。 但是,每個開發人員都應該至少了解測試的基礎知識。 它提高了他們所制造產品的信心,對于大多數公司而言,這是必需的。
In the React world, there is an amazing library called the react-testing-library
which helps you test your React Apps more efficiently. You use it with Jest.
在React世界中,有一個了不起的庫,稱為react-testing-library
,可幫助您更有效地測試React Apps。 您將其與Jest一起使用。
In this article, we will see the 8 simple steps you can take to start testing your React Apps like a boss.
在本文中,我們將看到您可以像執行老板一樣開始測試React Apps的8個簡單步驟。
Prerequisites
先決條件
Basics
基本
What is React Testing Library?
什么是React Testing庫?
1. How to create a test snapshot?
1.如何創建測試快照?
2. Testing DOM elements
2.測試DOM元素
3. Testing events
3.測試事件
4. Testing asynchronous actions
4.測試異步動作
5. Testing React Redux
5.測試React Redux
6. Testing React Context
6.測試React上下文
7. Testing React Router
7.測試React Router
8. Testing HTTP Request
8.測試HTTP請求
Final Thoughts
最后的想法
Next Steps
下一步
先決條件 (Prerequisites)
This tutorial assumes that you have at least a basic understanding of React. I will focus only on the testing part.
本教程假定您至少對React有基本的了解。 我將只關注測試部分。
And to follow along, you have to clone the project by running in your terminal:
接下來,您必須通過在終端中運行來克隆項目:
git clone https://github.com/ibrahima92/prep-react-testing-library-guide
Next, run:
接下來,運行:
yarn
Or, if you use NPM:
或者,如果您使用NPM:
npm install
And that's it! Now let's dive into some basics.
就是這樣! 現在讓我們深入一些基礎知識。
基本 (Basics)
Some key things will be used a lot in this article, and understanding their role can help you with your understanding.
本文將大量使用一些關鍵內容,了解它們的作用可以幫助您理解。
it or test
: describes the test itself. It takes as parameters the name of the test and a function that holds the tests.
it or test
:描述測試本身。 它以測試名稱和保存測試的函數為參數。
expect
: the condition that the test needs to pass. It will compare the received parameter to a matcher.
expect
:測試需要通過的條件。 它將接收到的參數與匹配器進行比較。
a matcher
: a function that is applied to the expected condition.
a matcher
:應用于預期條件的功能。
render
: the method used to render a given component.
render
:用于呈現給定組件的方法。
import React from 'react'
import {render} from '@testing-library/react'
import App from './App'it('should take a snapshot', () => {const { asFragment } = render(<App />)expect(asFragment(<App />)).toMatchSnapshot()})
});
As you can see, we describe the test with it
, then, use render
to display the App component and expect that asFragment(<App />)
matches toMatchSnapshot()
(the matcher provided by jest-dom).
如您所見,我們使用it
描述測試,然后使用render
顯示App組件,并期望asFragment(<App />)
與toMatchSnapshot()
匹配(由jest-dom提供的匹配器)。
By the way, the render
method returns several methods we can use to test our features. We also used destructuring to get the method.
順便說一句, render
方法返回了幾種我們可以用來測試功能的方法。 我們還使用了分解來獲取方法。
That being said, let's move on and learn more about the React Testing Library in the next section.
話雖如此,讓我們繼續并在下一節中進一步了解React測試庫。
什么是React Testing庫? (What is the React Testing Library?)
The React Testing Library is a very light-weight package created by Kent C. Dodds. It's a replacement for Enzyme and provides light utility functions on top of react-dom
and react-dom/test-utils
.
React Testing庫是由Kent C. Dodds創建的非常輕量級的軟件包。 它是Enzyme的替代品,并在react-dom
和react-dom/test-utils
之上提供了輕量級的實用程序功能。
The React Testing Library is a DOM testing library, which means that instead of dealing with instances of rendered React components, it handles DOM elements and how they behave in front of real users.
React Testing庫是一個DOM測試庫,這意味著它不處理渲染的React組件實例,而是處理DOM元素以及它們在實際用戶面前的行為。
It's a great library, it's (relatively) easy to start using, and it encourages good testing practices. Note – you can also use it without Jest.
這是一個很棒的庫,(相對)易于使用,并且鼓勵良好的測試實踐。 注意–您也可以在沒有Jest的情況下使用它。
"The more your tests resemble the way your software is used, the more confidence they can give you."
“您的測試越像軟件使用方式,就越能給您信心。”
So, let's start using it in the next section. By the way, you don't need to install any packages, since create-react-app
comes with the library and its dependencies.
因此,讓我們在下一部分中開始使用它。 順便說一句,您不需要安裝任何軟件包,因為該庫及其依賴項附帶了create-react-app
。
1.如何創建測試快照 (1. How to create a test snapshot)
A snapshot, as the name suggests, allows us to save the snapshot of a given component. It helps a lot when you update or do some refactoring, and want to get or compare the changes.
顧名思義,快照使我們可以保存給定組件的快照。 當您更新或進行一些重構,并希望獲取或比較更改時,它會很有幫助。
Now, let's take a snapshot of the App.js
file.
現在,讓我們對App.js
文件進行快照。
App.test.js
App.test.js
import React from 'react'
import {render, cleanup} from '@testing-library/react'
import App from './App'afterEach(cleanup)it('should take a snapshot', () => {const { asFragment } = render(<App />)expect(asFragment(<App />)).toMatchSnapshot()})
});
To take a snapshot, we first have to import render
and cleanup
. These two methods will be used a lot throughout this article.
要拍攝快照,我們首先必須導入render
和cleanup
。 在本文中,將經常使用這兩種方法。
render
, as you might guess, helps to render a React component. And cleanup
is passed as a parameter to afterEach
to just clean up everything after each test to avoid memory leaks.
render
,您可能已經猜到,有助于呈現一個作出React的組成部分。 并且將cleanup
作為參數傳遞給afterEach
以便在每次測試后清除所有內容,以避免內存泄漏。
Next, we can render the App component with render
and get back asFragment
as a returned value from the method. And finally, make sure that the fragment of the App component matches the snapshot.
接下來,我們可以渲染的應用組件render
,并取回asFragment
從方法的返回值。 最后,確保App組件的片段與快照匹配。
Now, to run the test, open your terminal and navigate to the root of the project and run the following command:
現在,要運行測試,請打開終端并導航到項目的根目錄,然后運行以下命令:
yarn test
Or, if you use npm:
或者,如果您使用npm:
npm test
As a result, it will create a new folder __snapshots__
and a file App.test.js.snap
in the src
which will look like this:
結果,它將在src
創建一個新文件夾__snapshots__
和一個App.test.js.snap
文件,如下所示:
App.test.js.snap
App.test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLPexports[`Take a snapshot should take a snapshot 1`] = `
<DocumentFragment><div class="App"><h1>Testing</h1></div>
</DocumentFragment>
`;
And if you make another change in App.js
, the test will fail, because the snapshot will no longer match the condition. To make it passes, just press u
to update it. And you'll have the updated snapshot in App.test.js.snap
.
而且,如果您在App.js
進行其他更改,則測試將失敗,因為快照將不再符合條件。 要使其通過,只需按u
即可對其進行更新。 并且您將在App.test.js.snap
擁有更新的快照。
Now, let's move on and start testing our elements.
現在,讓我們繼續并開始測試我們的元素。
2.測試DOM元素 (2. Testing DOM elements)
To test our DOM elements, we first have to look at the TestElements.js
file.
為了測試我們的DOM元素,我們首先必須查看TestElements.js
文件。
TestElements.js
TestElements.js
import React from 'react'const TestElements = () => {const [counter, setCounter] = React.useState(0)return (<><h1 data-testid="counter">{ counter }</h1><button data-testid="button-up" onClick={() => setCounter(counter + 1)}> Up</button><button disabled data-testid="button-down" onClick={() => setCounter(counter - 1)}>Down</button></>)}export default TestElements
Here, the only thing you have to retain is data-testid
. It will be used to select these elements from the test file. Now, let's write the unit test:
在這里,您唯一需要保留的就是data-testid
。 它將用于從測試文件中選擇這些元素。 現在,讓我們編寫單元測試:
Test if the counter is equal to 0:
測試計數器是否等于0:
TestElements.test.js
TestElements.test.js
import React from 'react';
import { render, cleanup } from '@testing-library/react';
import TestElements from './TestElements'afterEach(cleanup);it('should equal to 0', () => {const { getByTestId } = render(<TestElements />); expect(getByTestId('counter')).toHaveTextContent(0)});
As you can see, the syntax is quite similar to the previous test. The only difference is that we use getByTestId
to select the necessary elements (remember the data-testid
) and check if it passed the test. In others words, we check if the text content <h1 data-testid="counter">{ counter }</h1>
is equal to 0.
如您所見,語法與先前的測試非常相似。 唯一的區別是,我們使用getByTestId
選擇必要的元素(記住data-testid
)并檢查其是否通過了測試。 換句話說,我們檢查文本內容<h1 data-testid="counter">{ counter }</h1>
是否等于0。
Test if the buttons are enabled or disabled:
測試按鈕是啟用還是禁用:
TestElements.test.js
(add the following code block to the file)
TestElements.test.js
(將以下代碼塊添加到文件中)
it('should be enabled', () => {const { getByTestId } = render(<TestElements />);expect(getByTestId('button-up')).not.toHaveAttribute('disabled')});it('should be disabled', () => {const { getByTestId } = render(<TestElements />); expect(getByTestId('button-down')).toBeDisabled()});
Here, as usual, we use getByTestId
to select elements and check for the first test if the button has a disabled
attribute. And for the second, if the button is disabled or not.
在這里,與往常一樣,我們使用getByTestId
選擇元素并檢查按鈕是否具有disabled
屬性的第一次測試。 第二,按鈕是否被禁用。
And if you save the file or run again in your terminal yarn test
, the test will pass.
并且,如果您保存文件或在終端yarn test
再次運行,該測試將通過。
Congrats! Your first test has passed!
恭喜! 您的第一個測試已通過!
Now, let's learn how to test an event in the next section.
現在,讓我們在下一部分中學習如何測試事件。
3.測試事件 (3. Testing events)
Before writing our unit tests, let's first check what the TestEvents.js
looks like.
在編寫單元測試之前,讓我們首先檢查一下TestEvents.js
外觀。
TestEvents.js
TestEvents.js
import React from 'react'const TestEvents = () => {const [counter, setCounter] = React.useState(0)return (<><h1 data-testid="counter">{ counter }</h1><button data-testid="button-up" onClick={() => setCounter(counter + 1)}> Up</button><button data-testid="button-down" onClick={() => setCounter(counter - 1)}>Down</button></>)}export default TestEvents
Now, let's write the tests.
現在,讓我們編寫測試。
Test if the counter increments and decrements correctly when we click on buttons:
單擊按鈕時,測試計數器是否正確遞增和遞減:
TestEvents.test.js
TestEvents.test.js
import React from 'react';
import { render, cleanup, fireEvent } from '@testing-library/react';
import TestEvents from './TestEvents'afterEach(cleanup);it('increments counter', () => {const { getByTestId } = render(<TestEvents />); fireEvent.click(getByTestId('button-up'))expect(getByTestId('counter')).toHaveTextContent('1')});it('decrements counter', () => {const { getByTestId } = render(<TestEvents />); fireEvent.click(getByTestId('button-down'))expect(getByTestId('counter')).toHaveTextContent('-1')});
As you can see, these two tests are very similar except the expected text content.
如您所見,除了預期的文本內容之外,這兩個測試非常相似。
The first test fires a click event with fireEvent.click()
to check if the counter increments to 1 when the button is clicked.
第一個測試使用fireEvent.click()
觸發click事件,以檢查單擊按鈕時計數器是否增加為1。
And the second one checks if the counter decrements to -1 when the button is clicked.
第二個檢查單擊按鈕時計數器是否遞減到-1。
fireEvent
has several methods you can use to test events, so feel free to dive into the documentation to learn more.
fireEvent
有幾種可用于測試事件的方法,因此請隨時閱讀文檔以了解更多信息。
Now that we know how to test events, let's move on and learn in the next section how to deal with asynchronous actions.
現在我們知道了如何測試事件,讓我們繼續學習下一節如何處理異步操作。
4.測試異步動作 (4. Testing asynchronous actions)
An asynchronous action is something that can take time to complete. It can be an HTTP request, a timer, and so on.
異步操作需要花費一些時間才能完成。 它可以是HTTP請求,計時器等。
Now, let's check the TestAsync.js
file.
現在,讓我們檢查一下TestAsync.js
文件。
TestAsync.js
TestAsync.js
import React from 'react'const TestAsync = () => {const [counter, setCounter] = React.useState(0)const delayCount = () => (setTimeout(() => {setCounter(counter + 1)}, 500))return (<><h1 data-testid="counter">{ counter }</h1><button data-testid="button-up" onClick={delayCount}> Up</button><button data-testid="button-down" onClick={() => setCounter(counter - 1)}>Down</button></>)}export default TestAsync
Here, we use setTimeout()
to delay the incrementing event by 0.5s.
在這里,我們使用setTimeout()
將增量事件延遲0.5s。
Test if the counter is incremented after 0.5s:
測試計數器是否在0.5s后遞增:
TestAsync.test.js
TestAsync.test.js
import React from 'react';
import { render, cleanup, fireEvent, waitForElement } from '@testing-library/react';
import TestAsync from './TestAsync'afterEach(cleanup);it('increments counter after 0.5s', async () => {const { getByTestId, getByText } = render(<TestAsync />); fireEvent.click(getByTestId('button-up'))const counter = await waitForElement(() => getByText('1')) expect(counter).toHaveTextContent('1')});
To test the incrementing event, we first have to use async/await to handle the action because, as I said earlier, it takes time to complete.
為了測試遞增事件,我們首先必須使用async / await來處理該動作,因為正如我之前所說的,它需要時間才能完成。
Next, we use a new helper method getByText()
. This is similar to getByTestId()
, except that getByText()
selects the text content instead of id or data-testid.
接下來,我們使用新的輔助方法getByText()
。 這類似于getByTestId()
,除了getByText()
選擇文本內容而不是id或data-testid。
Now, after clicking to the button, we wait for the counter to be incremented with waitForElement(() => getByText('1'))
. And once the counter incremented to 1, we can now move to the condition and check if the counter is effectively equal to 1.
現在,單擊按鈕后,我們等待使用waitForElement(() => getByText('1'))
來增加計數器。 一旦計數器增加到1,我們現在可以移至條件并檢查計數器是否有效等于1。
That being said, let's now move to more complex test cases.
話雖如此,讓我們現在轉到更復雜的測試用例。
Are you ready?
你準備好了嗎?
5.測試React Redux (5. Testing React Redux)
If you're new to React Redux, this article might help you. Otherwise, let's check what the TestRedux.js
looks like.
如果您不熟悉React Redux, 本文可能會為您提供幫助。 否則,讓我們檢查一下TestRedux.js
外觀。
TestRedux.js
TestRedux.js
import React from 'react'
import { connect } from 'react-redux'const TestRedux = ({counter, dispatch}) => {const increment = () => dispatch({ type: 'INCREMENT' })const decrement = () => dispatch({ type: 'DECREMENT' })return (<><h1 data-testid="counter">{ counter }</h1><button data-testid="button-up" onClick={increment}>Up</button><button data-testid="button-down" onClick={decrement}>Down</button></>)}export default connect(state => ({ counter: state.count }))(TestRedux)
And for the reducer:
對于減速器:
store/reducer.js
store/reducer.js
export const initialState = {count: 0,}export function reducer(state = initialState, action) {switch (action.type) {case 'INCREMENT':return {count: state.count + 1,}case 'DECREMENT':return {count: state.count - 1,}default:return state}}
As you can see, there is nothing fancy – it's just a basic Counter Component handled by React Redux.
如您所見,沒有什么花哨的-它只是由React Redux處理的基本計數器組件。
Now, let's write the unit tests.
現在,讓我們編寫單元測試。
Test if the initial state is equal to 0:
測試初始狀態是否等于0:
TestRedux.test.js
TestRedux.test.js
import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import { render, cleanup, fireEvent } from '@testing-library/react';
import { initialState, reducer } from '../store/reducer'
import TestRedux from './TestRedux'const renderWithRedux = (component,{ initialState, store = createStore(reducer, initialState) } = {}
) => {return {...render(<Provider store={store}>{component}</Provider>),store,}
}afterEach(cleanup);it('checks initial state is equal to 0', () => {const { getByTestId } = renderWithRedux(<TestRedux />)expect(getByTestId('counter')).toHaveTextContent('0')})
There are a couple of things we need to import to test React Redux. And here, we create our own helper function renderWithRedux()
to render the component since it will be used several times.
我們需要導入一些內容來測試React Redux。 在這里,我們將創建自己的幫助器函數renderWithRedux()
來呈現組件,因為它將多次使用。
renderWithRedux()
receives as parameters the component to render, the initial state, and the store. If there is no store, it will create a new one, and if it doesn't receive an initial state or a store, it returns an empty object.
renderWithRedux()
接收要渲染的組件,初始狀態和存儲作為參數。 如果沒有存儲,它將創建一個新存儲,如果沒有收到初始狀態或存儲,則將返回一個空對象。
Next, we use render()
to render the component and pass the store to the Provider.
接下來,我們使用render()
渲染組件并將商店傳遞給Provider。
That being said, we can now pass the component TestRedux
to renderWithRedux()
to test if the counter is equal to 0
.
話雖如此,我們現在可以將組件TestRedux
傳遞給renderWithRedux()
以測試計數器是否等于0
。
Test if the counter increments and decrements correctly:
測試計數器是否正確遞增和遞減:
TestRedux.test.js
(add the following code block to the file)
TestRedux.test.js
(將以下代碼塊添加到文件中)
it('increments the counter through redux', () => {const { getByTestId } = renderWithRedux(<TestRedux />, {initialState: {count: 5}
})fireEvent.click(getByTestId('button-up'))expect(getByTestId('counter')).toHaveTextContent('6')
})it('decrements the counter through redux', () => {const { getByTestId} = renderWithRedux(<TestRedux />, {initialState: { count: 100 },})fireEvent.click(getByTestId('button-down'))expect(getByTestId('counter')).toHaveTextContent('99')
})
To test the incrementing and decrementing events, we pass an initial state as a second argument to renderWithRedux()
. Now, we can click on the buttons and test if the expected result matches the condition or not.
為了測試遞增和遞減事件,我們將初始狀態作為第二個參數傳遞給renderWithRedux()
。 現在,我們可以單擊按鈕并測試預期結果是否符合條件。
Now, let's move to the next section and introduce React Context.
現在,讓我們進入下一部分并介紹React Context。
React Router and Axios will come next – are you still with me?
接下來是React Router和Axios –您還和我在一起嗎?
6.測試React上下文 (6. Testing React Context)
If you're new to React Context, check out this article first. Otherwise, let's check the TextContext.js
file.
如果您不熟悉React Context,請先閱讀本文 。 否則,讓我們檢查TextContext.js
文件。
TextContext.js
TextContext.js
import React from "react"export const CounterContext = React.createContext()const CounterProvider = () => {const [counter, setCounter] = React.useState(0)const increment = () => setCounter(counter + 1)const decrement = () => setCounter(counter - 1)return (<CounterContext.Provider value={{ counter, increment, decrement }}><Counter /></CounterContext.Provider>)
}export const Counter = () => { const { counter, increment, decrement } = React.useContext(CounterContext) return (<><h1 data-testid="counter">{ counter }</h1><button data-testid="button-up" onClick={increment}> Up</button><button data-testid="button-down" onClick={decrement}>Down</button></>)
}export default CounterProvider
Now, the counter state is managed through React Context. Let's write the unit test to check if it behaves as expected.
現在,計數器狀態通過React Context進行管理。 讓我們編寫單元測試以檢查其行為是否符合預期。
Test if the initial state is equal to 0:
測試初始狀態是否等于0:
TextContext.test.js
TextContext.test.js
import React from 'react'
import { render, cleanup, fireEvent } from '@testing-library/react'
import CounterProvider, { CounterContext, Counter } from './TestContext'const renderWithContext = (component) => {return {...render(<CounterProvider value={CounterContext}>{component}</CounterProvider>)}
}afterEach(cleanup);it('checks if initial state is equal to 0', () => {const { getByTestId } = renderWithContext(<Counter />)expect(getByTestId('counter')).toHaveTextContent('0')
})
As in the previous section with React Redux, here we use the same approach, by creating a helper function renderWithContext()
to render the component. But this time, it receives only the component as a parameter. And to create a new context, we pass CounterContext
to the Provider.
與上一節關于React Redux的部分一樣,這里我們通過創建一個輔助函數renderWithContext()
來渲染組件,使用相同的方法。 但是這一次,它僅接收組件作為參數。 為了創建新的上下文,我們將CounterContext
傳遞給Provider。
Now, we can test if the counter is initially equal to 0 or not.
現在,我們可以測試計數器最初是否等于0。
Test if the counter increments and decrements correctly:
測試計數器是否正確遞增和遞減:
TextContext.test.js
(add the following code block to the file)
TextContext.test.js
(將以下代碼塊添加到文件中)
it('increments the counter', () => {const { getByTestId } = renderWithContext(<Counter />)fireEvent.click(getByTestId('button-up'))expect(getByTestId('counter')).toHaveTextContent('1')})it('decrements the counter', () => {const { getByTestId} = renderWithContext(<Counter />)fireEvent.click(getByTestId('button-down'))expect(getByTestId('counter')).toHaveTextContent('-1')})
As you can see, here we fire a click event to test if the counter increments correctly to 1 and decrements to -1.
如您所見,這里我們觸發一個click事件,以測試計數器是否正確地增加到1并減少到-1。
That being said, we can now move to the next section and introduce React Router.
話雖如此,我們現在可以進入下一部分并介紹React Router。
7.測試React Router (7. Testing React Router)
If you want to dive into React Router, this article might help you. Otherwise, let's check the TestRouter.js
file.
如果您想深入研究React Router, 這篇文章可能會對您有所幫助。 否則,讓我們檢查TestRouter.js
文件。
TestRouter.js
TestRouter.js
import React from 'react'
import { Link, Route, Switch, useParams } from 'react-router-dom'const About = () => <h1>About page</h1>const Home = () => <h1>Home page</h1>const Contact = () => {const { name } = useParams()return <h1 data-testid="contact-name">{name}</h1>
}const TestRouter = () => {const name = 'John Doe'return (<><nav data-testid="navbar"><Link data-testid="home-link" to="/">Home</Link><Link data-testid="about-link" to="/about">About</Link><Link data-testid="contact-link" to={`/contact/${name}`}>Contact</Link></nav><Switch><Route exact path="/" component={Home} /><Route path="/about" component={About} /><Route path="/about:name" component={Contact} /></Switch></>)
}export default TestRouter
Here, we have some components to render when navigating the Home page.
在這里,我們有一些導航主頁時要呈現的組件。
Now, let's write the tests:
現在,讓我們編寫測試:
TestRouter.test.js
TestRouter.test.js
import React from 'react'
import { Router } from 'react-router-dom'
import { render, fireEvent } from '@testing-library/react'
import { createMemoryHistory } from 'history'
import TestRouter from './TestRouter'const renderWithRouter = (component) => {const history = createMemoryHistory()return { ...render (<Router history={history}>{component}</Router>)}
}it('should render the home page', () => {const { container, getByTestId } = renderWithRouter(<TestRouter />) const navbar = getByTestId('navbar')const link = getByTestId('home-link')expect(container.innerHTML).toMatch('Home page')expect(navbar).toContainElement(link)
})
To test React Router, we have to first have a navigation history to start with. Therefore we use createMemoryHistory()
to well as the name guessed to create a navigation history.
要測試React Router,我們首先必須有一個導航歷史記錄。 因此,我們使用createMemoryHistory()
以及猜測的名稱來創建導航歷史記錄。
Next, we use our helper function renderWithRouter()
to render the component and pass history
to the Router
component. With that, we can now test if the page loaded at the start is the Home page or not. And if the navigation bar is loaded with the expected links.
接下來,我們使用輔助函數renderWithRouter()
渲染組件并將history
傳遞給Router
組件。 這樣,我們現在可以測試在開始時加載的頁面是否是主頁。 并在導航欄中加載預期的鏈接。
Test if it navigates to other pages with the parameters when we click on links:
單擊鏈接時,測試是否使用參數導航到其他頁面:
TestRouter.test.js
(add the following code block to the file)
TestRouter.test.js
(將以下代碼塊添加到文件中)
it('should navigate to the about page', ()=> {const { container, getByTestId } = renderWithRouter(<TestRouter />) fireEvent.click(getByTestId('about-link'))expect(container.innerHTML).toMatch('About page')
})it('should navigate to the contact page with the params', ()=> {const { container, getByTestId } = renderWithRouter(<TestRouter />) fireEvent.click(getByTestId('contact-link'))expect(container.innerHTML).toMatch('John Doe')
})
Now, to check if the navigation works, we have to fire a click event on the navigation links.
現在,要檢查導航是否有效,我們必須在導航鏈接上觸發click事件。
For the first test, we check if the content is equal to the text in the About Page, and for the second, we test the routing params and check if it passed correctly.
對于第一個測試,我們檢查內容是否與“關于頁面”中的文本相等,對于第二個測試,我們測試路由參數并檢查其是否正確傳遞。
We can now move to the final section and learn how to test an Axios request.
現在,我們可以轉到最后一節,學習如何測試Axios請求。
We're almost done!
我們快完成了!
8.測試HTTP請求 (8. Testing HTTP Request)
As usual, let's first see what the TextAxios.js
file looks like.
與往常一樣,讓我們??首先看一下TextAxios.js
文件的外觀。
TextAxios.js
TextAxios.js
import React from 'react'
import axios from 'axios'const TestAxios = ({ url }) => {const [data, setData] = React.useState()const fetchData = async () => {const response = await axios.get(url)setData(response.data.greeting) } return (<><button onClick={fetchData} data-testid="fetch-data">Load Data</button>{ data ?<div data-testid="show-data">{data}</div>:<h1 data-testid="loading">Loading...</h1>}</>)
}export default TestAxios
As you can see here, we have a simple component that has a button to make a request. And if the data is not available, it will display a loading message.
如您在這里看到的,我們有一個簡單的組件,該組件帶有一個用于發出請求的按鈕。 并且如果數據不可用,它將顯示一條加載消息。
Now, let's write the tests.
現在,讓我們編寫測試。
Test if the data are fetched and displayed correctly:
測試是否已正確提取和顯示數據:
TextAxios.test.js
TextAxios.test.js
import React from 'react'
import { render, waitForElement, fireEvent } from '@testing-library/react'
import axiosMock from 'axios'
import TestAxios from './TestAxios'jest.mock('axios')it('should display a loading text', () => {const { getByTestId } = render(<TestAxios />)expect(getByTestId('loading')).toHaveTextContent('Loading...')
})it('should load and display the data', async () => {const url = '/greeting'const { getByTestId } = render(<TestAxios url={url} />)axiosMock.get.mockResolvedValueOnce({data: { greeting: 'hello there' },})fireEvent.click(getByTestId('fetch-data'))const greetingData = await waitForElement(() => getByTestId('show-data'))expect(axiosMock.get).toHaveBeenCalledTimes(1)expect(axiosMock.get).toHaveBeenCalledWith(url)expect(greetingData).toHaveTextContent('hello there')
})
This test case is a bit different because we have to deal with an HTTP request. And to do that, we have to mock an axios request with the help of jest.mock('axios')
.
這個測試用例有些不同,因為我們必須處理一個HTTP請求。 為此,我們必須借助jest.mock('axios')
模擬axios請求。
Now, we can use axiosMock
and apply a get()
method to it. Finally we will use the Jest function mockResolvedValueOnce()
to pass the mocked data as a parameter.
現在,我們可以使用axiosMock
并對其應用一個get()
方法。 最后,我們將使用Jest函數mockResolvedValueOnce()
來傳遞mockResolvedValueOnce()
數據作為參數。
With that, now for the second test we can click to the button to fetch the data and use async/await to resolve it. And now we have to test 3 things:
這樣,現在對于第二個測試,我們可以單擊按鈕來獲取數據并使用async / await來解決它。 現在我們必須測試3件事:
- If the HTTP request has been done correctly 如果HTTP請求已正確完成
If the HTTP request has been done with the
url
如果HTTP請求已通過
url
完成- If the data fetched matches the expectation. 如果獲取的數據符合期望。
And for the first test, we just check if the loading message is displayed when we have no data to show.
對于第一個測試,我們只檢查沒有數據要顯示時是否顯示加載消息。
That being said, we're now done with the 8 simple steps to start testing your React Apps.
話雖如此,我們現在已經完成了8個簡單步驟來開始測試React Apps。
Don't be scared to test anymore.
不要害怕測試了。
最后的想法 (Final Thoughts)
The React Testing Library is a great package for testing React Apps. It gives us access to jest-dom
matchers we can use to test our components more efficiently and with good practices. Hopefully this article was useful, and it will help you build robust React apps in the future.
React Testing庫是用于測試React Apps的出色軟件包。 它使我們能夠訪問jest-dom
匹配器,我們可以使用它們來更有效地并通過良好實踐來測試我們的組件。 希望本文對您有所幫助,并在將來幫助您構建功能強大的React應用。
You can find the finished project here
您可以在這里找到完成的項目
Thanks for reading it!
感謝您閱讀!
Read more articles ?- ?Subscribe to my newsletter ? - ? Follow me on twitter
文章 - 訂閱我的新聞通訊 - 在Twitter上關注我
You can read other articles like this on my blog.
您可以在我的博客上閱讀其他類似的文章 。
下一步 (Next Steps)
React Testing Library docs
React Testing庫文檔
React Testing Library Cheatsheet
React測試庫備忘單
Jest DOM matchers cheatsheet
笑話DOM匹配器備忘單
Jest Docs
笑話文檔
翻譯自: https://www.freecodecamp.org/news/8-simple-steps-to-start-testing-react-apps-using-react-testing-library-and-jest/
react jest測試