@testing-library/react: 测试你的 React 组件

@testing-library/react: 测试你的 React 组件

@testing-library[1] 是一系列建立在 DOM Testing Library[2](@testing-library/dom)基础上的包的集合。用来测试 UI 组件,不鼓励测试实现细节(比如组件内部状态、方法甚至生命周期),而是鼓励从用户使用的角度进行测试。

作为初级教程,篇幅有效,本文只讨论 @testing-library/react[3] 的使用,有其他需求的同学,可以查阅对应框架的使用文档[4]

  • 官网地址:https://testing-library.com/docs/react-testing-library/intro
  • repo 地址:https://github.com/testing-library/react-testing-library

@testing-library/react

React Testing Library 在 DOM Testing Library 的基础上构建,通过添加用于处理 React 组件的 API 来增强功能。

为了避免测试组件实现细节,而是专注于以组件使用的方式进行测试,从而方便理解与对组件重构(实现方式变化但功能不变)。@testing-library/react 基于 react-domreact-dom/test-utils 提供了一些轻量级的工具函数。

另外,@testing-library/reactJest[5] 为一等公民,所以默认跟 Jest 配合很好。不过也能自定义使用其他测试框架[6]

项目准备

Create React App[7]  对 React Testing Library 提供了开箱支持,不过由于各种原因[8],React 官方文档已不再提及,所以我们使用 Next.js 来整合 @testing-library/react

Next.js 从 12 开始已经内置了 Jest 支持[9],配置起来非常简单。首先安装依赖:

npm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
  • jest-environment-jsdom[10]Jest 的默认环境是 Node.js 环境[11]。如果正在构建 Web 应用程序,可以使用 jsdom 来代替浏览器类似的环境。要开始使用 JSDOM 测试环境,如果尚未安装,则必须安装 jest-environment-jsdom 软件包
  • @testing-library/jest-dom[12]:提供了一组自定义的 jest 匹配器,你可以使用它们来扩展 jest。比如:.toBeInTheDocument()

方便起见,只需在测试设置文件(tests setup file)中导入 @testing-library/jest-dom,你就可以开始使用了:

import '@testing-library/jest-dom'

在你的项目根目录下创建一个 jest.config.mjs 文件,并添加以下内容:

import nextJest from 'next/jest.js'

const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir'./',
})

// Add any custom config to be passed to Jest
/** @type {import('jest').Config} */
const config = {
  // Add more setup options before each test is run
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testEnvironment'jest-environment-jsdom',
}

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config)

在幕后,next/jest 会自动为你配置 Jest,包括:

  • 使用 SWC 设置 transform
  • 自动 Mock 样式表(.css.module.css 及其 scss 变体)、图像导入和 next/font
  • .env(及所有变体)加载到 process.env
  • 从测试解析(test resolving)和 transforms 中忽略 node_modules
  • 从测试解析中忽略 .next
  • 加载 next.config.js,寻找启用 SWC transforms 的标志

创建测试文件

package.json 文件中添加 test 脚本

{
  "scripts": {
    "dev""next dev",
    "build""next build",
    "start""next start",
    "test""jest --watch"
  }
}

创建第一个测试文件

你的项目现在已准备好运行测试。按照 Jest 的惯例,在项目根目录下添加 __tests__ 文件夹以进行测试。

例如,我们可以添加一个测试来检查 <Home /> 组件是否成功渲染标题:

import { render, screen } from '@testing-library/react'
import Home from '../pages/index'

describe('Home', () => {
  it('renders a heading', () => {
    render(<Home />)

    const heading = screen.getByRole('heading', {
      name/welcome to next.js!/i,
    })

    expect(heading).toBeInTheDocument()
  })
})

可选地,添加一个快照测试来跟踪您的 <Home /> 组件中的任何意外更改:

import { render } from '@testing-library/react'
import Home from '../pages/index'
 
it('renders homepage unchanged', () => {
  const { container } = render(<Home />)
  expect(container).toMatchSnapshot()
})

执行测试

运行 npm run test 来执行测试套件。在你的测试通过或失败后,你会注意到一系列交互式 Jest 命令列表,这些命令将有助于你添加更多的测试。

其他案例

案例一:render/userEvent/screen

// import react-testing methods
import {render, screen} from '@testing-library/react'
// userEvent library simulates user interactions by dispatching the events that would happen if the interaction took place in a browser.
import userEvent from '@testing-library/user-event'
// add custom jest matchers from jest-dom
import '@testing-library/jest-dom'
// the component to test
import Fetch from './fetch'

test('loads and displays greeting'async () => {
  // Render a React element into the DOM
  render(<Fetch url="/greeting" />)

  await userEvent.click(screen.getByText('Load Greeting'))
  // wait before throwing an error if it cannot find an element
  await screen.findByRole('heading')

  // assert that the alert message is correct using
  // toHaveTextContent, a custom matcher from jest-dom.
  expect(screen.getByRole('heading')).toHaveTextContent('hello there')
  expect(screen.getByRole('button')).toBeDisabled()
})

完整代码看这里[13]

案例二:render

import {render} from '@testing-library/react'
import '@testing-library/jest-dom'

test('renders a message', () => {
  const {asFragment, getByText} = render(<Greeting />)
  expect(getByText('Hello, world!')).toBeInTheDocument()
  expect(asFragment()).toMatchInlineSnapshot(`
    <h1>Hello, World!</h1>
  `
)
})

案例三:renderHook

import {renderHook} from '@testing-library/react'

test('returns logged in user', () => {
  const {result, rerender} = renderHook((props = {}) => props, {
    initialProps: {name'Alice'},
  })
  expect(result.current).toEqual({name'Alice'})
  rerender()
  expect(result.current).toEqual({nameundefined})
})

注意:@testing-library/react v13.1.0 才增加 renderHook API 的支持,而且还限定在 React18。  如果你的项目使用 React17-,那么最高只能安装 v12.1.5 版本,测试 React Hook 的话,需要借助 @testing-library/react-hooks 库具体信息看这里的链接[14]

// React 18, @testing-library/react v13.1.0+
import { renderHook } from '@testing-library/react'

// React 17-, @testing-library/react-hooks
import { renderHook } from '@testing-library/react-hooks'

完整 API 及其他资源

完整 API

由于 @testing-library/react 是基于 @testing-library/dom 的封装,re-export 了 @testing-library/dom API。因此完整 API 要同时参考 @testing-library/react 的拓展 API[15]renderrenderHook 等)和 @testing-library/dom API[16]

其他资源

  • Jest 文档[17]
  • React Testing Library[18]
  • Testing Playground[19] – 如果你不知道该使用什么 API 选择页面元素,可以参考这里的官方推荐

引用链接

[1]

@testing-library: https://www.npmjs.com/org/testing-library

[2]

DOM Testing Library: https://testing-library.com/docs/dom-testing-library/intro

[3]

@testing-library/react: https://testing-library.com/docs/react-testing-library/intro

[4]

查阅对应框架的使用文档: https://testing-library.com/docs/dom-testing-library/install

[5]

Jest: https://jestjs.io/

[6]

自定义使用其他测试框架: https://testing-library.com/docs/react-testing-library/setup#using-without-jest

[7]

Create React App: https://create-react-app.dev/

[8]

各种原因: https://www.linkedin.com/pulse/end-era-react-team-longer-recommends-create-app-vivek-dwivedi

[9]

Next.js 从 12 开始已经内置了 Jest 支持: https://nextjs.org/docs/pages/building-your-application/optimizing/testing#setting-up-jest-with-the-rust-compiler

[10]

jest-environment-jsdom: https://jestjs.io/docs/tutorial-jquery

[11]

Jest 的默认环境是 Node.js 环境: https://jestjs.io/docs/configuration#testenvironment-string

[12]

@testing-library/jest-dom: https://www.npmjs.com/package/@testing-library/jest-dom

[13]

看这里: https://testing-library.com/docs/react-testing-library/example-intro#full-example

[14]

看这里的链接: https://github.com/testing-library/react-hooks-testing-library#a-note-about-react-18-support

[15]

@testing-library/react 的拓展 API: https://testing-library.com/docs/react-testing-library/api

[16]

@testing-library/dom API: https://testing-library.com/docs/dom-testing-library/api

[17]

Jest 文档: https://jestjs.io/docs/getting-started

[18]

React Testing Library: https://testing-library.com/docs/react-testing-library/intro/

[19]

Testing Playground: https://testing-playground.com/


原文始发于微信公众号(写代码的宝哥):@testing-library/react: 测试你的 React 组件

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/243957.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!