React Testing Library入门
1. 简介
React Testing Library 基于DOM Testing Library的基础上添加一些API,主要用于测试React组件。如果是其它的技术栈,可以选择对应的Testing Library库。该库在使用过程并不关注组件的内部实现,而是更关注测试。该库基于react-dom和react-dom/test-utils,是以上两者的轻量实现。
注:React Testing Library官方文档需翻墙查看。
2. 安装
npm install --save-dev @testing-library/react
注:如果使用Create React App初始化React应用时,会有选项提示是否要使用React Testing Library
3. 基本能力
- 组件渲染(render)
- 元素查找(get/query/find)
- 事件触发(fireEvent)
4. 使用
在编写单元测试过程中,可以按照AAA模式实现。
- Arrange 编排,使用render渲染组件。
render(component)
- Act 执行,使用fireEvent去触发用户行为。
fireEvent.click(element)
- Assert 断言,对期望的结果予以判断。
expect(result).matcher()
//search.js
function Search({ value, onChange, children }) {
return (
<div>
<label htmlFor="search">{children}</label>
<input
id="search"
type="text"
value={value}
onChange={onChange}
/>
</div>
);
}
//search.test.js
import React from 'react'
//引入@testing-library/react提供的方法
import {render, fireEvent, screen} from '@testing-library/react'
import search from './search'
describe('Search', () => {
test('calls the onChange callback handler', () => {
const onChange = jest.fn();
// Arrange 编排
render(
<Search value="" onChange={onChange}>
Search:
</Search>
);
//Act 执行
fireEvent.change(screen.getByRole('textbox'), {
target: { value: 'JavaScript' },
});
//Assert 断言
expect(onChange).toHaveBeenCalledTimes(1);
});
});
更多例子:fetch
推荐教程:How to use React Testing Library Tutorial
5.常用API
render
render的参数:
render(
ui: React.ReactElement<any>,
options?: { //基本不用
container, //
baseElement,
wrapper, //
queries //用于自定义选择器
}
)
render的结果:
{
...queries, //选择器,例如(get/query/find)By(Text/Label/...)
container: HTMLDivElement,//自动创建一个div,并插入到body中
baseElement: HTMLBodyElement, //相当于document.body
debug: Function, //打印当前document.body
rerender: Function, //重新渲染组件
unmount: Function, //组件卸载,此时container.innerHTML === ''
asFragment:Function //记录某个时刻的dom
}
render的例子:
//列出的是常用的
{queryByText, container, baseElement, debug, rerender, unmount} = render(conponent)
文档:https://testing-library.com/docs/react-testing-library/api#render
cleanup
相当于给组件置成unmount,一般在afterEach()中执行,如果使用的Jest,不需要在afterEach中手动设置,框架已默认每次test结束后执行cleanup。
Queries
search type (单个元素) |
search type (多个元素) |
function (查询单个元素) |
适用场景 |
---|---|---|---|
getBy | getAllBy | getByText getByRole getByLabelText getByPlaceholderText getByAltText getByDisplayValue |
由于只返回元素或error,适用于确定该元素存在的情况 |
queryBy | queryAllBy | queryByText queryByRole queryByLabelText queryByPlaceholderText queryByAltText queryByDisplayValue |
用于元素可能不存在 |
findBy | findAllBy | findByText findByRole findByLabelText findByPlaceholderText findByAltText findByDisplayValue |
用于异步元素 |
关于具体差别的例子可以看:https://www.robinwieruch.de/react-testing-library
LabelText: getByLabelText: <label for="search" />
PlaceholderText: getByPlaceholderText: <input placeholder="Search" />
AltText: getByAltText: <img alt="profile" />
DisplayValue: getByDisplayValue: <input value="JavaScript" />
TestId: getByTestId: <div data-testid='search'></div>
也可以自定义选择器:https://testing-library.com/docs/react-testing-library/setup#add-custom-queries
详细queries,查阅:https://testing-library.com/docs/react-testing-library/cheatsheet#queries
fireEvent
fireEvent(node, event)
act
对react-dom/test-utils中的act函数进行了一层包装。act的作用是在你进行断言之前,保证所有由组件渲染、用户交互以及数据获取产生的更新全部在dom实现。
act(() => {
// render components
});
act(() => {
// fireEvent
});
// make assertions
waitFor
用于异步
waitFor(Promise)
screen
screen的方法继承自queries, queries有的能力都有,此外还增加了debug()的能力.
6.补充
(1) 关于更多自定义的东西,例如render、选择器以及与Jest有的配置,查阅官方文档吧,写得也是很清楚哦!
(2)对于dom的一些断言,可以添加testing-library库提供的jest-dom/extend-expect来更好得对dom进行断言。
//引入
import '@testing-library/jest-dom/extend-expect'
匹配器概览:
//Custom matchers
toBeDisabled
toBeEnabled
toBeEmptyDOMElement
toBeInTheDocument
toBeInvalid
toBeRequired
toBeValid
toBeVisible
toContainElement
toContainHTML
toHaveAccessibleDescription
toHaveAccessibleName
toHaveAttribute
toHaveClass
toHaveFocus
toHaveFormValues
toHaveStyle
toHaveTextContent
toHaveValue
toHaveDisplayValue
toBeChecked
toBePartiallyChecked
toHaveErrorMessage
//Deprecated matchers
toBeEmpty
toBeInTheDOM
toHaveDescription
具体用法,可以查阅文档
好啦,关于React testing Library的东西基本都涵盖了,至于更深层的东西,就去查阅源码吧!