📜  如何使用 Jest 测试 React 组件?

📅  最后修改于: 2022-05-13 01:56:15.247000             🧑  作者: Mango

如何使用 Jest 测试 React 组件?

React 是一个前端开源 JavaScript 库,用于构建交互式用户界面。 React 专注于单页应用程序,更普遍地称为 SPA。

测试是开发的一个重要方面。它检查应用程序是否按预期运行,并在对应用程序进行任何不需要的更改时保护它。有各种测试库,例如 chai、mocha 等。在本教程中,我们将使用 jest 库和反应测试库来测试 React 组件。

先决条件:

  • React 简介
  • React 中的函数式组件

所需模块:

  • npm
  • 反应

创建 React 应用程序并设置:

第 1 步:您将使用 create-react-app 启动一个新项目,因此打开您的终端并输入。

npx create-react-app jest-testing

第 2 步:使用以下命令切换到 jest-testing 文件夹。

cd tic-tac-toe-react

第 3 步:切换到 src 文件夹并使用以下命令删除不必要的东西

cd src
rm*

第四步:在 src 文件夹中创建 components 文件夹

mkdir components

第 5 步:创建一个 Button 文件夹和一个 Text 文件夹

mkdir Button,Text

第 6 步:在 Button 文件夹中创建一个 Button.js 文件和 Button.test.js 文件。

touch Button.js Button.test.js

注意:测试文件的名称应与组件的名称相同,并应后跟 .test.js 扩展名,因为当使用npm test命令运行测试时,React 会自动检查所有带有 .test 的文件名扩展并运行测试。

第 7 步:在 Text 文件夹中创建一个 Text.js 文件和 Text.test.js 文件。

touch Text.js Text.test.js

第 8 步:在 src 文件夹中,创建 App.js、index.js 和 App.test.js 文件。

touch App.js index.js App.test.js

项目结构:项目中的文件结构将如下所示。

项目结构

示例:使用基本代码设置所有文件,以在单击按钮时切换文本 GeeksForGeeks。

index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
  
ReactDOM.render(
  
    
  ,
  document.getElementById('root')
);


Button.js
const Button = ({ setToggle, btnTxt }) => {
  
    // data-testid is a testing id 
    // which is used only during tests
    return 
}
  
export default Button;


Text.js
const Text = ({toggle, displayTxt}) => {
  
    // data-testid is a testing id
    // which is used only during tests
    return 

{toggle? displayTxt : ""}

}    export default Text;


App.js
import Button from "./components/Button/Button";
import Text from "./components/Text/Text";
import { useState } from "react";
  
const App = () => {
  const [toggle, setToggle] = useState(true);
  
  return (
    
             
  ); }    export default App;


Button.test.js
import { render, screen, cleanup } from "@testing-library/react";
// Importing the jest testing library
import '@testing-library/jest-dom'
import Button from "./Button";
  
// afterEach function runs after each test suite is executed
afterEach(() => {
    cleanup(); // Resets the DOM after each test suite
})
  
describe("Button Component" ,() => {
    const setToggle= jest.fn(); 
    render(


Text.test.js
import { render, screen, cleanup } from "@testing-library/react";
  
// Importing the jest testing library
import '@testing-library/jest-dom'
import Text from "./Text";
  
// afterEach function runs after each test suite is executed
afterEach(() => {
    cleanup(); 
})
  
describe("Text Component" ,() => {
  
    // Test 1
    test("Text Rendering", () => {
        render();
        const text = screen.getByTestId("text");
        expect(text).toBeInTheDocument();
    })
  
    // Test 2
    test("Displayed Text when toggle is set to true", () => {
        render() 
        const text = screen.getByTestId("text"); 
        expect(text).toHaveTextContent("GeeksForGeeks"); 
    })
  
    // Test 3
    test("Displayed Text when toggle is set to false", () => {
        render();
        const text = screen.getByTestId("text"); 
        expect(text).toBeEmptyDOMElement(); 
    })
})


App.js
import { render, screen, cleanup, fireEvent } from "@testing-library/react";
// Importing the jest testing library
import '@testing-library/jest-dom'
import App from "./App";
  
// afterEach function runs after each test suite is executed
afterEach(() => {
    cleanup(); 
})
  
describe("App Component" ,() => {
      
    // Test 1
    test("App Rendering", () => {
        render(); // Rendering the App
        const text = screen.getByTestId("text"); 
        const button = screen.getByTestId("button");
        expect(button).toBeInTheDocument();
        expect(text).toBeInTheDocument();
    })
  
    // Test 2
    test("Default Text", () => {
        render(); 
        const text = screen.getByTestId("text"); 
        expect(text).toHaveTextContent("GeeksForGeeks");
    })
      
    // Test 3
    test("Toggling Text", () => {
        render();
        const text = screen.getByTestId("text"); 
        const button = screen.getByTestId("button"); 
        expect(text).toHaveTextContent("GeeksForGeeks");
        fireEvent.click(button); 
        expect(text).toBeEmptyDOMElement(); 
        fireEvent.click(button);
        expect(text).toHaveTextContent("GeeksForGeeks");
    })
})


按钮.js

const Button = ({ setToggle, btnTxt }) => {
  
    // data-testid is a testing id 
    // which is used only during tests
    return 
}
  
export default Button;

文本.js

const Text = ({toggle, displayTxt}) => {
  
    // data-testid is a testing id
    // which is used only during tests
    return 

{toggle? displayTxt : ""}

}    export default Text;

应用程序.js

import Button from "./components/Button/Button";
import Text from "./components/Text/Text";
import { useState } from "react";
  
const App = () => {
  const [toggle, setToggle] = useState(true);
  
  return (
    
             
  ); }    export default App;

输出:

运行以下命令来启动应用程序:

npm start

创建了一个简单的应用程序,它在按下按钮时切换文本 GeeksForGeeks。

现在基本的应用程序已经设置好了,我们可以开始测试它了。在测试应用程序之前,让我们了解一些重要的测试方法。

  • render(Component):在模拟屏幕上渲染给定的组件。
  • screen:对具有各种有用测试功能的模拟屏幕的引用。
  • cleanup():重置 DOM。
  • afterEach(callback 函数):在运行每个测试套件后运行作为参数给出的回调函数。
  • beforeEach(callback 函数):在运行每个测试套件之前运行作为参数给出的回调函数。
  • describe(nameOfTestSuite, callback 函数):定义一个包含许多单元测试的测试套件(Callback 函数包含单元测试)。
  • test(nameOfTest, callback 函数):定义要执行的测试。
  • fireEvent:模拟指定事件。

测试按钮组件:我们将对按钮组件执行两个测试。

  • 测试 1:测试按钮是否正确呈现到 DOM。
  • 测试 2:测试按钮是否显示作为道具传递的文本。

Button.test.js

import { render, screen, cleanup } from "@testing-library/react";
// Importing the jest testing library
import '@testing-library/jest-dom'
import Button from "./Button";
  
// afterEach function runs after each test suite is executed
afterEach(() => {
    cleanup(); // Resets the DOM after each test suite
})
  
describe("Button Component" ,() => {
    const setToggle= jest.fn(); 
    render(

输出:

使用以下命令运行测试:

npm test

测试结果

我们可以看到有两个测试套件失败,一个通过了。原因是没有为 Text 组件和 App 组件设计测试。所以唯一通过的测试套件是按钮组件。

测试文本组件:我们将对文本组件执行三个测试。

  • 测试 1:测试文本元素是否正确呈现到 DOM。
  • 测试 2:在切换设置为 true 时测试文本元素的内容。
  • 测试 3:在切换设置为 false 时测试文本元素的内容。

文本.test.js

import { render, screen, cleanup } from "@testing-library/react";
  
// Importing the jest testing library
import '@testing-library/jest-dom'
import Text from "./Text";
  
// afterEach function runs after each test suite is executed
afterEach(() => {
    cleanup(); 
})
  
describe("Text Component" ,() => {
  
    // Test 1
    test("Text Rendering", () => {
        render();
        const text = screen.getByTestId("text");
        expect(text).toBeInTheDocument();
    })
  
    // Test 2
    test("Displayed Text when toggle is set to true", () => {
        render() 
        const text = screen.getByTestId("text"); 
        expect(text).toHaveTextContent("GeeksForGeeks"); 
    })
  
    // Test 3
    test("Displayed Text when toggle is set to false", () => {
        render();
        const text = screen.getByTestId("text"); 
        expect(text).toBeEmptyDOMElement(); 
    })
})

输出:

使用以下命令运行测试:

npm test

测试结果

测试应用程序组件:测试应用程序组件也称为集成测试,因为我们在集成按钮和文本组件时测试应用程序。我们将对 App 组件执行三个测试。

  • 测试一:测试是否所有组件都已渲染
  • 测试2:测试文本元素的默认值
  • 测试3:测试按钮的切换能力

应用程序.js

import { render, screen, cleanup, fireEvent } from "@testing-library/react";
// Importing the jest testing library
import '@testing-library/jest-dom'
import App from "./App";
  
// afterEach function runs after each test suite is executed
afterEach(() => {
    cleanup(); 
})
  
describe("App Component" ,() => {
      
    // Test 1
    test("App Rendering", () => {
        render(); // Rendering the App
        const text = screen.getByTestId("text"); 
        const button = screen.getByTestId("button");
        expect(button).toBeInTheDocument();
        expect(text).toBeInTheDocument();
    })
  
    // Test 2
    test("Default Text", () => {
        render(); 
        const text = screen.getByTestId("text"); 
        expect(text).toHaveTextContent("GeeksForGeeks");
    })
      
    // Test 3
    test("Toggling Text", () => {
        render();
        const text = screen.getByTestId("text"); 
        const button = screen.getByTestId("button"); 
        expect(text).toHaveTextContent("GeeksForGeeks");
        fireEvent.click(button); 
        expect(text).toBeEmptyDOMElement(); 
        fireEvent.click(button);
        expect(text).toHaveTextContent("GeeksForGeeks");
    })
})

输出:使用以下命令运行测试:

npm test

测试结果