利用 Jest 测试 React 组件

利用 Jest 测试 React 组件

利用Jest测试React组件

Jest 是一个由 facebook 维护的测试框架,在本文中,我们将利用 Jest 来测试 React 组件。我们将首先了解如何在纯 JavaScript 函数上使用 Jest,然后再了解它提供的一些开箱即用的特性,这些特性旨在使测试 React 应用程序变得更容易。

img

注意,Jest 并不是专门针对 React 的测试框架,你可以使用它来测试任何 JavaScript 应用程序。然而,它提供的一些特性对于测试用户界面非常方便,这就是它非常适合 React 的原因。

示例程序

在可以进行测试前,我们需要一个应用程序,在此以一个待办事项列表为例,大家可以从 Github 中克隆该应用:testing-react-with-jest。

示例项目利用 webpack 进行构建,

应用程序的入口点是 src/index.js,它将 <App> 组件呈现到 HTML 中:

import React from 'react'
import {
    
     render } from 'react-dom'
import App from './App.jsx'

render(
  <App />,
  document.getElementById('root')
)

应用程序中组件树层级结构如下:

img

应用中使用到的初始状态数据及业务逻辑在 src/state/index.js 中:

export const initialTodos = [ ... ]

export const addTodoItem = (todos, todo) => {
    
     ... }

export const toggleTodoItem = (todos, id) => {
    
     ... }

export const removeTodoItem = (todos, id) => {
    
     ... }

UI 界面效果:

img

扫描二维码关注公众号,回复: 14251173 查看本文章

Jest使用

Jest 于 2014 年首次发布,虽然它最初引起了很多人的兴趣,但该项目一度处于休眠状态。然而,Facebook 投入了大量精力来改进 Jest,随后发布了一些更新的版本,与最初的开源版本相比,Jest 的唯一相似之处是名称和徽标,其他一切都已更改和重写。

安装与配置Jest

首先,我们需要安装 Jest,由于我们也在使用 Babel,所以一并安装相关的模块,使 Jest 和 Babel 开箱即用:

$ npm install jest babel-jest --save-dev
# 或
$ yarn add jest babel-jest --dev

在项目根目录下创建 __tests__ 目录,Jest 希望在一个__tests__ 目录中找到我们的测试,这已经成为 JavaScript 社区的流行约定,当然,如果你对创建 __tests__ 目录统一管理不感冒,Jest 也支持查找任意的 *.test.js*.spec.js 文件。

下面我们来测试我们的状态函数。

继续创建 __tests__/state/index.test.js,在正式测试之前,我们先看是否能够正常进行测试:

describe('数字加减算术运算', () => {
    
    
  test('3加2减5等于0', () => {
    
    
    expect(3 + 2 - 5).toBe(0)
  })
})

package.json 文件中添加 npm scripts 任务:

{
    
    
  "scripts": {
    
    
    "test": "jest"
  }
}

然后在命令行中执行测试任务:

$ npm test

运行结果:

img

在 Jest 中,我们可以根据需要使用 describetest 嵌套测试,describe 创建一个将几个相关测试组合在一起的块,test 是运行测试的方法。在此测试中,使用了 expecttoBe 来检测两个值是否完全相同。相关 API 使用我们可以在 Jest 官方 API 文档 中进行查阅,本文中我们也可以来了解一些 Jest 的断言。

测试业务逻辑

我们已经通过一个示例看到了 Jest 在测试中的工作,下面我们来测试状态逻辑中的一个函数 removeTodoItem

export const removeTodoItem = (todos, id) => todos.filter(todo => todo.id !== id)

removeTodoItem 接收要删除待办事项的当前状态与待删除待办事项的 id。

利用 describetest 编写该测试:

describe('待办事项操作测试', () => {
    
    
  test('删除待办事项', () => {
    
    
    
  })
})

可能大家也会看到其它文档中使用 it 来代替 test,其实 it 是作为 test 的别名使用的,二者是相同的作用。

下面开始编写断言,首先,可以创建一个初始状态 todos 数组,然后将它传递给 removeTodoItem,再传递我们想要删除的新的待办事项 id,removeTodoItem 会返回完成后的状态,可以如下定义:

describe('待办事项操作测试', () => {
    
    
  test('删除待办事项', () => {
    
    
    const todos = [
      {
    
    id: 1, title: '复习 React 基础知识', completed: true},
      {
    
    id: 2, title: '复习 React Hooks 使用', completed: false}
    ]
    const finishedTodos = removeTodoItem(todos, 1)

    expect(finishedTodos).toEqual([{
    
    id: 2, title: '复习 React Hooks 使用', completed: false}])
  })
})

在这里我们使用 toEqual 来做出断言,它对引用类型的对象将进行“深”比较是否相等。toBe 一般用于原始类型的值的比较,例如字符串、数字等类型,toEqual 通常在数组和对象上使用。

在命令行中执行 npm test

img

可以看到测试通过。

测试React组件

不建议在 React 组件上编写太多的测试,任何你想测试的内容,比如业务逻辑,还是建议从组件中独立出来放在单独的函数中,就像上边测试状态函数一样。但有时测试一些 React 交互是很有必要的,如要确保用户在单击某个按钮时使用正确的参数去调用特定函数。

如果利用 Create React App 来创建项目,从 3.3 以后的版本中已自带官方推荐的 testing-library,本文暂不讨论 testing-library。

安装与配置Enzyme

为了编写我们的测试,先安装 Enzyme,这是一个由 Airbnb 编写的包装库,它使得测试 React 组件变得更容易。同时,我们还要为我们使用的 React 不同版本安装适配器,本例中使用 React v17.x,目前还没有官方适配器可用,但也有社区版本:

$ npm install --save-dev enzyme @wojtekmaj/enzyme-adapter-react-17
# 或
$ yarn add --dev enzyme @wojtekmaj/enzyme-adapter-react-17

对于 React v16.x,可以使用 enzyme-adapter-react-16

接着对 Enzyme 进行少量相关配置,在项目根目录下创建 setup-enzyme.js 文件:

import {
    
     configure } from 'enzyme'
import Adapter from '@wojtekmaj/enzyme-adapter-react-17'

configure({
    
     adapter: new Adapter() })

然后在项目根目录下创建 jest.config.js 文件:

module.exports = {
    
    
  setupFilesAfterEnv: [
    './setup-enzyme.js'
  ],
  testEnvironment: 'jsdom'
}

这告诉 Jest 在执行任何测试之前,为我们运行 setup-tests.js 文件,由于测试的是 Web 应用程序,所以使用浏览器类似的环境 jsdom 来代替。

编写组件渲染测试

接下来我们就可以编写测试了,我们来测试 TodoItem 组件是否能够在段落中渲染待办事项文本。

创建 __tests__/components/TodoItem.test.js

import React from 'react'
import {
    
     mount } from 'enzyme'
import TodoItem from '../../src/components/TodoItem.jsx'

describe('待办事项-列表项组件', () => {
    
    
  test('渲染待办事项列表项', () => {
    
    
    
  })
})

enzyme 中导入 mount,用于渲染组件,这样就可以检查输出并对其进行断言测试了。即使我们在 Node 环境中运行测试,也可以编写需要的 DOM 并进行测试,因为 Jest 中允许你使用 jsdom 库操作 DOM,这样就不必每次都启动浏览器来测试了。

接下来我们完成测试编写,整个测试如下:

import React from 'react'
import {
    
     mount } from 'enzyme'
import TodoItem from '../../src/components/TodoItem.jsx'

describe('待办事项-列表项组件', () => {
    
    
  test('渲染待办事项列表项', () => {
    
    
    const todo = {
    
    id: 2, title: '复习 React Hooks 使用', completed: false}
    const wrapper = mount(
      <TodoItem todo={
    
    todo} />
    )
    const p = wrapper.find('p')
    expect(p.text()).toBe('复习 React Hooks 使用')
  })
})

简单说明一下,我们可以使用 mount 来创建 TodoItem,然后调用 wrapper.find() 传递一个 CSS 选择器来查找节点,由于示例的 DOM 很简单,所以直接使用 p 元素选择器查找,这和使用 jQuery 类似。最后,可以断言段落中的文本内容应该是“复习 React Hooks 使用”。

img

可以看到测试通过。

编写交互测试

下面我们来测试当点击待办事项列表项中的段落时,修改待办事项的完成状态。

Jest 中提供了 spy (间谍)的开箱即用的功能,一个 spy 是一个函数,你不用关心它的实现,只需关心它的调用时间与调用方式,当我们要监视函数时可以考虑使用它。

要修改待办事项的完成状态,需要传递 toggle 属性,它是一个函数,我们现在来测试当用户点击时,该函数被使用正确的参数进行调用。

首先使用 jest.fn() 创建一个 spy

const toggle = jest.fn()

这为我们提供了一个可以监视并确保它被正确调用的函数。

接下来渲染 TodoItem 组件:

const toggle = jest.fn()
const wrapper = mount(
  <TodoItem todo={
    
    todo} toggle={
    
    toggle} />
)

然后查找 DOM 节点并模拟用户触发点击事件:

const p = wrapper.find('p')
p.simulate('click')

simulate() 用于模拟用户事件。

剩下的就是断言 spy 函数被正确调用,整个测试应该如下:

test('点击修改待办事项状态', () => {
    
    
  const toggle = jest.fn()
  const todo = {
    
    id: 2, title: '复习 React Hooks 使用', completed: false}
  const wrapper = mount(
    <TodoItem todo={
    
    todo} toggle={
    
    toggle} />
  )
  const p = wrapper.find('p')
  p.simulate('click')
  expect(toggle).toBeCalledWith(2)
})

我们期望使用待办事项的 id 作为参数进行调用,可以用 expect(toggle).toBeCalledWith(2) 来断言。这样,我们的测试就完成了:

img

测试通过。

总结

Jest 被大量的使用,已成为 JavaScript 开发人员最爱的测试框架之一,相信它会变得更好。在测试方面,它拥有速度快、API 简单、易配置、IDE 整合、多项目并行等优势,相信随着大家的使用,你一定会爱上它的。

文章示例 Github 仓库:https://github.com/itrainhub/testing-react-with-jest

测试通过。

总结

Jest 被大量的使用,已成为 JavaScript 开发人员最爱的测试框架之一,相信它会变得更好。在测试方面,它拥有速度快、API 简单、易配置、IDE 整合、多项目并行等优势,相信随着大家的使用,你一定会爱上它的。

文章示例 Github 仓库:https://github.com/itrainhub/testing-react-with-jest

- End -

*陆荣涛前端学习交流Q群858752519
加群备注:CSDN推荐
请添加图片描述

猜你喜欢

转载自blog.csdn.net/sdasadasds/article/details/125144025