简介
react-testing-library
是一个用于测试 React 组件的库,其方式类似于最终用户使用组件的方式。它非常适合 React 组件和应用程序的单元测试、集成和 e2e 测试。它更直接地与 DOM 节点一起使用,因此建议与 jest-dom 一起使用,这样可以方便的做断言。
react-testing-library
可以取代enzyme库与jest结合来对react组件进行测试。
本文参考地址:
官网地址:
配置
安装:
npm install --save @testing-library/react @testing-library/jest-dom
或
yarn add @testing-library/react
yarn add @testing-library/jest-dom
全局配置(结合jest.config.js使用)
在 tests/setupTests.js
中引入的全局的配置:
// react-testing-library 将您的组件显示为document.body,
// 这将为 jest-dom 添加一个自定义断言
import '@testing-library/jest-dom';
基础
渲染组件
render:render(<App />)
函数渲染组件。您应该可以在测试中访问React组件。同时使用screen.debug();
在运行测试文件时,命令行中会输出已经渲染的组件html结构。
选择元素
搜索类型
screen.getByText
screen.getByText('Search:');
通过文本来选择元素。
getByText
如果找不到元素,默认情况下会方便地引发错误。因此无需写显示断言。
该getByText
函数接受一个字符串作为输入,也接受一个正则表达式。字符串参数用于完全匹配,而正则表达式可用于部分匹配。
screen.getByRole
getByRole
函数通常用于通过aria-label属性检索元素,通过它们在React Testing Library中的可访问性角色来选择元素。
通常不必为HTML元素显式分配aria角色,因为DOM已经具有附加到HTML元素的隐式角色,例如input元素。它是getByText
的有力竞争者。
语法:getByRole(‘type’,{name:‘name’});
type: 元素类型
name:[aria-label属性名]
扩展
其他的对于特定元素的搜索类型:
- screen.getByLabelText 与给定匹配的标签,然后找到与该标签关联的元素。
- screen.getByPlaceholderText
- screen.getByAltText
- screen.getByDisplayValue
LabelText: getByLabelText:<label for="search" />
PlaceholderText: getByPlaceholderText:<input placeholder="Search" />
AltText: getByAltText:<img alt="profile" />
DisplayValue: getByDisplayValue:<input value="JavaScript" />
- screen.getByTestId :
getByTestId
需要HTML中分配属性data-testid
搜索变体
思考:
何时使用getBy vs queryBy?
当我们断言不存在的元素时使用queryBy
何时使用findBy?
findBy搜索变量用于异步元素,这些元素最终会出现。
如何选择多个元素?
所有的搜索变体都可以用All扩展,例 getAllBy\queryAllBy\findAllBy ,它们都返回一个元素数组,并且可以再次与搜索类型相关联。
getBy*
默认的搜索变体,例screen.getByText
和screen.getByRole
。这也是测试React组件时默认使用的搜索变体。它返回一个元素或者错误。
queryBy*
screen.queryByText(/Searches for JavaScript/)
跟getBy访问的相同搜索类型进行扩展,如下:
- queryByText
- queryByRole
- queryByLabelText
- queryByPlaceholderText
- queryByAltText
- queryByDisplayValue
findBy*
example:expect(await screen.findByText(/Signed in as/)).toBeInTheDocument();
与getBy访问的相同搜索类型进行扩展,如下
- findByText
- findByRole
- findByLabelText
- findByPlaceholderText
- findByAltText
- findByDisplayValue
选择多个元素
screen.getAllBy*、screen.queryAllBy* 、screen.findAllBy*
返回结果一览表
输出选择元素
screen.debug(screen.getAllBy*/getBy*)
screen.debug(screen.queryAllBy*/queryBy*)
screen.debug(screen.findAllBy*/findBy*)
断言
React测试库扩展了jest的api,定义了自己的断言函数,所有的断言函数包含在@testing-library/jest-dom
包中。详情:内置断言库
- toBeDisabled
- toBeEnabled
- toBeEmpty
- toBeEmptyDOMElement
- toBeInTheDocument
- toBeInvalid
- toBeRequired 表单字段必须
- toBeValid
- toBeVisible
- toContainElement
- toContainHTML
- toHaveAttribute
- toHaveClass 有某一个类名
- toHaveFocus
- toHaveFormValues
- toHaveStyle
- toHaveTextContent
- toHaveValue
- toHaveDisplayValue
- toBeChecked
- toBePartiallyChecked
- toHaveDescription
事件
fireEvent
例:
fireEvent.change(screen.getByRole('textbox'), {
target: { value: 'JavaScript' },
});
fireEvent函数接受一个元素(这里是textbox角色的输入字段)和一个事件(这里是一个值为“JavaScript”的事件,此处只触发change事件,并不触发keyDown,keyUp,keyPress事件)。
用户事件
userEvent
例如:
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import App from './App';
describe('App', () => {
test('renders App component', async () => {
render(<App />);
// wait for the user to resolve
await screen.findByText(/Signed in as/);
expect(screen.queryByText(/Searches for JavaScript/)).toBeNull();
await userEvent.type(screen.getByRole('textbox'), 'JavaScript');
expect(
screen.getByText(/Searches for JavaScript/)
).toBeInTheDocument();
});
});
Whenever possible, use userEvent over fireEvent when using React Testing Library
回调处理程序
使用jest模拟函数模拟回调处理程序,与具体查看jest文档
异步
使用jest模拟请求函数,具体查看jest文档
findBy搜索变量用于异步元素,这些元素最终会出现。可以用它等得某元素的出现,可以使用更为明确的等待promise:await act(() => promise);,