react jest測試_如何使用React測試庫和Jest開始測試React應用

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-domreact-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.

要拍攝快照,我們首先必須導入rendercleanup 。 在本文中,將經常使用這兩種方法。

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件事:

  1. If the HTTP request has been done correctly

    如果HTTP請求已正確完成
  2. If the HTTP request has been done with the url

    如果HTTP請求已通過url完成

  3. 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測試

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390538.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390538.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390538.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

面試題 17.10. 主要元素

題目 數組中占比超過一半的元素稱之為主要元素。給你一個 整數 數組&#xff0c;找出其中的主要元素。若沒有&#xff0c;返回 -1 。請設計時間復雜度為 O(N) 、空間復雜度為 O(1) 的解決方案。 示例 1&#xff1a; 輸入&#xff1a;[1,2,5,9,5,9,5,5,5] 輸出&#xff1a;5 …

簡單團隊-爬取豆瓣電影T250-項目進度

本次主要講解一下我們的頁面設計及展示最終效果&#xff1a; 頁面設計主要用到的軟件是&#xff1a;html&#xff0c;css&#xff0c;js&#xff0c; 主要用的編譯器是&#xff1a;sublime&#xff0c;dreamweaver&#xff0c;eclipse&#xff0c;由于每個人使用習慣不一樣&…

鴿子為什么喜歡盤旋_如何為鴿子回避系統設置數據收集

鴿子為什么喜歡盤旋鴿子回避系統 (Pigeon Avoidance System) Disclaimer: You are reading Part 2 that describes the technical setup. Part 1 gave an overview of the Pigeon Avoidance System and Part 3 provides details about the Pigeon Recognition Model.免責聲明&a…

scrum認證費用_如何獲得專業Scrum大師的認證-快速和慢速方式

scrum認證費用A few months ago, I got the Professional Scrum Master Certification (PSM I). 幾個月前&#xff0c;我獲得了專業Scrum Master認證(PSM I)。 This is a trending certification nowadays, because most companies operate with some sort of agile methodolo…

981. 基于時間的鍵值存儲

創建一個基于時間的鍵值存儲類 TimeMap&#xff0c;它支持下面兩個操作&#xff1a; set(string key, string value, int timestamp) 存儲鍵 key、值 value&#xff0c;以及給定的時間戳 timestamp。 get(string key, int timestamp) 返回先前調用 set(key, value, timesta…

前端開發-DOM

文檔對象模型&#xff08;Document Object Model&#xff0c;DOM&#xff09;是一種用于HTML和XML文檔的編程接口。它給文檔提供了一種結構化的表示方法&#xff0c;可以改變文檔的內容和呈現方式。我們最為關心的是&#xff0c;DOM把網頁和腳本以及其他的編程語言聯系了起來。…

css 繪制三角形_解釋CSS形狀:如何使用純CSS繪制圓,三角形等

css 繪制三角形Before we start. If you want more free content but in video format. Dont miss out on my Youtube channel where I publish weekly videos on FrontEnd coding. https://www.youtube.com/user/Weibenfalk----------Are you new to web development and CSS?…

密碼學基本概念(一)

區塊鏈兄弟社區&#xff0c;區塊鏈技術專業問答先行者&#xff0c;中國區塊鏈技術愛好者聚集地 作者&#xff1a;于中陽 來源&#xff1a;區塊鏈兄弟 原文鏈接&#xff1a;http://www.blockchainbrother.com/article/72 著權歸作者所有。商業轉載請聯系作者獲得授權&#xff0c…

JAVA-初步認識-第十三章-多線程(驗證同步函數的鎖)

一. 至于同步函數用的是哪個鎖&#xff0c;我們可以驗證一下&#xff0c;借助原先賣票的例子 對于程序中的num&#xff0c;從100改為400&#xff0c;DOS的結果顯示的始終都是0線程&#xff0c;票號最小都是1。 票號是沒有問題的&#xff0c;因為同步了。 有人針對只出現0線程&a…

追求卓越追求完美規范學習_追求新的黃金比例

追求卓越追求完美規范學習The golden ratio is originally a mathematical term. But art, architecture, and design are inconceivable without this math. Everyone aspires to golden proportions as beautiful and unattainable perfection. By visualizing data, we chal…

leetcode 275. H 指數 II

給定一位研究者論文被引用次數的數組&#xff08;被引用次數是非負整數&#xff09;&#xff0c;數組已經按照 升序排列 。編寫一個方法&#xff0c;計算出研究者的 h 指數。 h 指數的定義: “h 代表“高引用次數”&#xff08;high citations&#xff09;&#xff0c;一名科研…

Node js開發中的那些旮旮角角 第一部

#前戲 上一周是我到現公司來最忙碌的&#xff08;最有意思的&#xff09;一周了&#xff0c;為什么這么說呢&#xff1f;因為項目中需要提供服務端對用戶病人信息的一個匯總并以email的形式分享信息的接口&#xff0c;在幾天的時間里調研處理一套實施方案。我們服務端是Node.js…

文件2. 文件重命名

servlet對本機已存在的文件進行重命名。 .jsp界面 1 <form action"<%basePath %>fileAction" method"get" >2 <table>3 <tr>4 <td>輸入文件路徑</td>5 <td&…

js字符串slice_JavaScript子字符串示例-JS中的Slice,Substr和Substring方法

js字符串sliceIn daily programming, we often need to work with strings. Fortunately, there are many built-in methods in JavaScript that help us while working with arrays, strings and other data types. We can use these methods for various operations like sea…

leetcode 218. 天際線問題

城市的天際線是從遠處觀看該城市中所有建筑物形成的輪廓的外部輪廓。給你所有建筑物的位置和高度&#xff0c;請返回由這些建筑物形成的 天際線 。 每個建筑物的幾何信息由數組 buildings 表示&#xff0c;其中三元組 buildings[i] [lefti, righti, heighti] 表示&#xff1a…

[Android Pro] 終極組件化框架項目方案詳解

cp from : https://blog.csdn.net/pochenpiji159/article/details/78660844 前言 本文所講的組件化案例是基于自己開源的組件化框架項目github上地址github.com/HelloChenJi…其中即時通訊(Chat)模塊是單獨的項目github上地址github.com/HelloChenJi… 1.什么是組件化&#xff…

如何寫一個vue指令directive

舉個例子 &#xff1a;clickoutside.js const clickoutsideContext clickoutsideContext;export default {/*param el 指令所綁定的元素param binding {Object} param vnode vue編譯生成的虛擬節點*/bind (el, binding, vnode) {const documentHandler function(e) {console.…

安裝angular cli_Angular 9適用于初學者—如何使用Angular CLI安裝第一個應用程序

安裝angular cliAngular is one of the most popular JavaScript frameworks created and developed by Google. In the last couple of years, ReactJS has gained a lot of interest and has become the most popular modern JS library in the industry. But this doesn’t …

leetcode 1818. 絕對差值和

給你兩個正整數數組 nums1 和 nums2 &#xff0c;數組的長度都是 n 。 數組 nums1 和 nums2 的 絕對差值和 定義為所有 |nums1[i] - nums2[i]|&#xff08;0 < i < n&#xff09;的 總和&#xff08;下標從 0 開始&#xff09;。 你可以選用 nums1 中的 任意一個 元素來…