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测试

react jest测试_如何使用React测试库和Jest开始测试React应用相关推荐

  1. spock测试_用于混合Spock 1.x和JUnit 5测试的Maven项目设置

    spock测试 我为Maven创建了一个示例Groovy项目,该项目在一个项目中混合了Spock测试和JUnit 5测试. 在下一节中,我将描述如何设置这种Maven项目. 在项目中启用Groovy ...

  2. 窗体测试只能用于本地测试_爆料:微软 Win10X 将首先用于测试单屏笔记本

    本文转自:IT之家 作者:玄隐 去年,微软宣布了新的桌面操作系统"Windows 10X".Windows 10X是专为Surface Neo等双屏或折叠屏设备而设计的,但正如我们 ...

  3. postman跨域测试_安装使用Hoppscotch构建API请求访问与测试

    什么是API请求构建工具 在移动互联网时代,面向多端开发成为主流,需要向用户提供如:安卓App.苹果App.WAP.小程序.Web网页等等多种应用入口,这些入口称为前端.而为不同前端提供数据和业务信息 ...

  4. 型人格 disc测试_(在线测试)表演型人格障碍 在线筛查测试表演性人格障碍...

    (在线测试)表演型人格障碍,在线筛查人格障碍测试,表演型人格障碍,又称寻求注意型人格障碍或癔症型人格障碍,女性较多见. 下面是专业级的,人格障碍筛查测试,也叫人格障碍测试量表,PDQ-4+ (严肃的. ...

  5. react sql格式化_为SQL Server数据库损坏做准备; 初步React与分析

    react sql格式化 Corruption is a looming thought through every administrator's mind, from sysadmins to d ...

  6. 一个神奇的测试_神奇的心理测试:一个问题就能测试出你的情商!超准慎测

    测试导语: 面对情感,你是十足的理性派,还是跟随自己的心不断去尝试的那个人?想知道你的情商到底如何吗? 测试开始: 假设你特别害怕一项极限运动,但是你的TA却很喜欢,想邀请你一起去,你会? A.杀了我 ...

  7. java开发的游戏测试_用java编写。模拟一个简单的测试打字速度的游戏

    请高手帮我看看我的程序哪里出现错误了,输出打字速度时出错importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.A ...

  8. fpu测试_解毒盖世G600散热器,3900X超频测试能不能压住?

    一.前言 又是一年双十一,很多玩家在这个时候都会选择购买自己的人生第一台电脑,毕竟这个阶段不买,就得等618才会有这种价格了~ 而CPU散热器作为硬件DIY中不可或缺的一块,一提起长城,我想不少玩家首 ...

  9. fpu测试_惠普暗影精灵6锐龙版测试:四代Ryzen真香

    一说到惠普的游戏本,最出名的就是暗影精灵系列了.这个系列如今已经出到第六代了,外观有了很大变化的同时,也用上了AMD最新的锐龙4000系列处理器.今天我们就嫖到了一台暗影精灵6锐龙版,一起来看看它的表 ...

最新文章

  1. Ubuntu 14.04 64位上安装Adobe reader 9.5.5
  2. eval解析JSON中的注意点
  3. Mac 上 iterm2 和 VSCode 终端中的字体设置建议
  4. 解决老版本eclipse无法完全替换主题的问题
  5. MIPS SDE简介
  6. 基于@AspectJ配置Spring AOP之一--转
  7. 我的第五个网页制作:pre、html转义、abbr标签的使用
  8. python字典顺序遍历_在Python中,如何按已排序的键顺序遍历字典?
  9. Greenplum 数据库架构分析
  10. 把网卡指定给vm虚拟机_为VMWare虚拟网卡指定静态的MAC地址
  11. 案例 月工作列表 c# 1614099857
  12. js检测是否安装java_js判断当前浏览器是否是源生app的webview
  13. mysql 查询 int类型日期转换成datetime类型
  14. 『vulnhub系列』dpwwn-1—Linux计划任务提权
  15. java NBA2010,关于一个NBA球队连续夺冠的SQL查询问题,解法很精妙~
  16. Pr 入门教程如何减少音频中的噪音和混响?
  17. Power Management of Hybrid DRAM/PRAM-Based Main Memory
  18. 基于蓝墨云班课的翻转课堂实践
  19. PayPal全球报告:逾三分之一中国网购消费者在海淘
  20. cocos creator 优量汇广告接入

热门文章

  1. odoo10 继承(扩展)、模块数据
  2. Squid 访问控制配置
  3. zedboard--zynq使用自带外设IP让ARM PS访问FPGA(八) 转载
  4. 2064: 分裂 - BZOJ
  5. ibatis 中 $与#的区别
  6. HDOJ---2236 无题II[二分枚举+匈牙利]
  7. NSRange的用法【转】
  8. mssql性能优化[转](教你写出高质量的SQL语句)(二)
  9. centos7安装oracle12c 三
  10. 3.Contructor(构造器)模式—精读《JavaScript 设计模式》Addy Osmani著