跳至主要内容

API

React 测试库 重新导出了 DOM 测试库 中的所有内容,以及以下方法


render

function render(
ui: React.ReactElement<any>,
options?: {
/* You won't often use this, expand below for docs on options */
},
): RenderResult

渲染到附加到 document.body 的容器中。

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

render(<div />)
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>
`)
})

render 选项

你通常不需要指定选项,但如果你需要,这里有一些你可以作为第二个参数提供给 render 的可用选项。

container

默认情况下,React 测试库 将创建一个 div 并将其附加到 document.body,你的 React 组件将渲染在此处。如果你通过此选项提供自己的 HTMLElement container,它不会自动附加到 document.body

例如:如果你正在对 tablebody 元素进行单元测试,它不能是 div 的子元素。在这种情况下,你可以指定 table 作为渲染 container

const table = document.createElement('table')

const {container} = render(<TableBody {...props} />, {
container: document.body.appendChild(table),
})

baseElement

如果指定了 container,则它默认为该值,否则默认为 document.body。它用作查询的基础元素,以及当你使用 debug() 时打印的内容。

hydrate

如果将 hydrate 设置为 true,则它将使用 ReactDOM.hydrate 进行渲染。如果你正在使用服务器端渲染并使用 ReactDOM.hydrate 来挂载你的组件,这可能很有用。

legacyRoot

危险

此选项仅在测试使用 React 18 及更早版本运行时可用。

默认情况下,我们将使用对并发功能的支持进行渲染(即 ReactDOMClient.createRoot)。但是,如果你正在处理需要像 React 17 中那样进行渲染的遗留应用程序(即 ReactDOM.render),那么你应该通过设置 legacyRoot: true 来启用此选项。

wrapper

将 React 组件作为 wrapper 选项传递,使其渲染在内部元素周围。这对于为常见数据提供者创建可重用的自定义渲染函数最为有用。有关示例,请参阅 设置

queries

要绑定的查询。覆盖来自 DOM 测试库 的默认集,除非合并。

// Example, a function to traverse table contents
import * as tableQueries from 'my-table-query-library'
import {queries} from '@testing-library/react'

const {getByRowColumn, getByText} = render(<MyTable />, {
queries: {...queries, ...tableQueries},
})

有关使用实用函数创建自定义查询的指南,请参阅 辅助函数

还可以通过遵循 自定义渲染指南 在全局范围内添加自定义查询。

render 结果

render 方法返回一个具有几个属性的对象

...queries

render 的最重要的功能是,来自 DOM 测试库 的查询会自动返回,它们的首个参数绑定到 baseElement,它默认是 document.body

有关完整的列表,请参阅 查询

示例

const {getByLabelText, queryAllByTestId} = render(<Component />)

container

渲染的 React 元素的包含 DOM 节点(使用 ReactDOM.render 渲染)。它是一个 div。这是一个普通的 DOM 节点,因此你可以调用 container.querySelector 等来检查其子元素。

提示:要获取渲染元素的根元素,请使用 container.firstChild

注意:当该根元素是一个 React 片段 时,container.firstChild 仅获取该片段的第一个子元素,而不是片段本身。

🚨 如果你发现自己使用 container 来查询渲染的元素,那么你应该重新考虑!其他查询旨在更能抵御对要测试的组件所做的更改。避免使用 container 来查询元素!

baseElement

包含 React 元素在容器中渲染的 DOM 节点。如果你没有在 render 的选项中指定 baseElement,它将默认为 document.body

当要测试的组件在容器 div 之外渲染某些内容时,这很有用,例如,当你想对直接在 body 中渲染其 HTML 的门户组件进行快照测试时。

注意:render 返回的查询会查看 baseElement,因此你可以在没有 baseElement 的情况下使用查询来测试门户组件。

debug

注意:建议使用 screen.debug 代替。

此方法是 console.log(prettyDOM(baseElement)) 的快捷方式。

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

const HelloWorld = () => <h1>Hello World</h1>
const {debug} = render(<HelloWorld />)
debug()
// <div>
// <h1>Hello World</h1>
// </div>
// you can also pass an element: debug(getByTestId('messages'))
// and you can pass all the same arguments to debug as you can
// to prettyDOM:
// const maxLengthToPrint = 10000
// debug(getByTestId('messages'), maxLengthToPrint, {highlight: false})

这是一个围绕 prettyDOM 的简单包装器,prettyDOM 也是公开的,它来自 DOM 测试库

rerender

如果你测试正在进行道具更新的组件以确保道具被正确更新,这可能会更好(参见 指南原则部分)。也就是说,如果你更愿意在测试中更新渲染组件的道具,则可以使用此函数来更新渲染组件的道具。

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

const {rerender} = render(<NumberDisplay number={1} />)

// re-render the same component with different props
rerender(<NumberDisplay number={2} />)

参见示例页面

unmount

这将导致渲染的组件被卸载。这对于测试你的组件从页面中删除时会发生什么很有用(例如,测试你不留下会导致内存泄漏的事件处理程序)。

此方法是对 ReactDOM.unmountComponentAtNode 的一个非常小的抽象。

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

const {container, unmount} = render(<Login />)
unmount()
// your component has been unmounted and now: container.innerHTML === ''

asFragment

返回渲染的组件的 DocumentFragment。如果你需要避免实时绑定并查看你的组件对事件的反应,这可能很有用。

import React, {useState} from 'react'
import {render, fireEvent} from '@testing-library/react'

const TestComponent = () => {
const [count, setCounter] = useState(0)

return (
<button onClick={() => setCounter(count => count + 1)}>
Click to increase: {count}
</button>
)
}

const {getByText, asFragment} = render(<TestComponent />)
const firstRender = asFragment()

fireEvent.click(getByText(/Click to increase/))

// This will snapshot only the difference between the first render, and the
// state of the DOM after the click event.
// See https://github.com/jest-community/snapshot-diff
expect(firstRender).toMatchDiffSnapshot(asFragment())

cleanup

卸载使用 render 挂载的 React 树。

如果你的测试框架(例如 mocha、Jest 或 Jasmine)将全局 afterEach() 函数注入到测试环境中,则会自动调用此函数。如果没有,你需要在每次测试后调用 cleanup()

例如,如果你正在使用 ava 测试框架,那么你需要使用 test.afterEach 钩子,如下所示

import {cleanup, render} from '@testing-library/react'
import test from 'ava'

test.afterEach(cleanup)

test('renders into document', () => {
render(<div />)
// ...
})

// ... more tests ...

如果你调用了 render 但没有调用 cleanup,可能会导致内存泄漏和非“幂等”测试(这会导致测试中难以调试的错误)。


act

这是一个围绕 react act 函数 的轻量级包装器。如果你的 react 版本支持 act,它所做的就是将所有参数转发给 act 函数。出于一致性考虑,建议使用来自 @testing-library/react 的导入,而不是 react

renderHook

这是一个围绕 render 的便利包装器,它使用自定义测试组件。该 API 源自一种流行的测试模式,主要对发布钩子的库很有用。你应该首选 render,因为自定义测试组件会导致更易读和更健壮的测试,因为你要测试的内容不会隐藏在抽象后面。

function renderHook<
Result,
Props,
Q extends Queries = typeof queries,
Container extends Element | DocumentFragment = HTMLElement,
BaseElement extends Element | DocumentFragment = Container
>(
render: (initialProps: Props) => Result,
options?: RenderHookOptions<Props, Q, Container, BaseElement>,
): RenderHookResult<Result, Props>

示例

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

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

renderHook 选项

renderHook 选项 initialProps

声明在首次调用时传递给渲染回调的道具。如果你在没有道具的情况下调用 rerender,这些道具不会传递。

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({name: undefined})
})

注意:当将 renderHookwrapperinitialProps 选项一起使用时,initialProps 不会传递给 wrapper 组件。要向 wrapper 组件提供道具,请考虑以下解决方案

const createWrapper = (Wrapper, props) => {
return function CreatedWrapper({ children }) {
return <Wrapper {...props}>{children}</Wrapper>;
};
};

...

{
wrapper: createWrapper(Wrapper, { value: 'foo' }),
}

renderHook 选项 wrapper

参见 renderwrapper 选项

renderHook 结果

renderHook 方法返回一个包含以下属性的对象。

result

保存渲染回调最近一次 **提交** 的返回值。

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

const {result} = renderHook(() => {
const [name, setName] = useState('')
React.useEffect(() => {
setName('Alice')
}, [])

return name
})

expect(result.current).toBe('Alice')

请注意,该值保存在 result.current 中。可以将 result 视为最近一次 **提交** 值的 ref

rerender

使用新 props 重新渲染之前渲染的渲染回调。

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

const {rerender} = renderHook(({name = 'Alice'} = {}) => name)

// re-render the same hook with different props
rerender({name: 'Bob'})

unmount

卸载测试钩子。

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

const {unmount} = renderHook(({name = 'Alice'} = {}) => name)

unmount()

configure

更改全局选项。可以在 配置选项 中看到基本用法。

React Testing Library 还提供专用的选项。

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

configure({reactStrictMode: true})

configure 选项

reactStrictMode

启用后,<StrictMode> 将渲染在内部元素周围。默认值为 false