在 React Testing Library 中,screen
对象和直接使用 getByText
, getByTestId
等方法之间的主要区别在于它们的使用方式和上下文。然而,从功能的角度来看,它们实际上是相互关联的,因为 screen
对象提供了一组封装好的查询方法,这些方法内部最终会调用如 getByText
, getByTestId
等查询函数。
直接使用 getByText
, getByTestId
等
当你直接调用 getByText
, getByTestId
等方法时,你通常是在组件的渲染结果(即 DOM)上直接进行查询。这些方法是由 React Testing Library 提供的,用于从渲染的组件树中查找元素。如果找不到匹配的元素,这些方法会抛出一个错误。
例如:
import { render, getByText } from '@testing-library/react';
const { container } = render(<MyComponent />);
const element = getByText(container, 'some text'); // 注意:这里的用法实际上是不推荐的,因为 getByText 应该直接通过 render 的结果调用
但更常见的做法是直接从 render
函数的返回结果中调用这些方法,或者通过 screen
对象调用,如下所示:
import { render, screen } from '@testing-library/react';
render(<MyComponent />);
const element = screen.getByText('some text'); // 推荐的方式
使用 screen
对象
screen
对象是一个全局查询助手,它允许你在整个 DOM 中进行查询,而无需担心当前的渲染上下文。这在你需要查询不在当前组件直接作用域内的元素时特别有用,比如模态框、下拉菜单等。
screen
对象提供了一组与 getBy*
类似的方法,如 screen.getByText
, screen.getByTestId
, screen.getByRole
等。使用这些方法时,你不需要指定一个特定的容器元素,因为 screen
已经代表了整个 DOM。
区别总结
- 使用上下文:直接使用
getByText
等方法时,你可能需要指定一个容器元素(尽管在大多数情况下,你会从render
函数的返回结果中直接调用它们)。而screen
对象则不需要,因为它已经代表了整个 DOM。 - 全局性:
screen
对象提供了一种全局查询的方式,这在某些情况下非常有用,比如当你需要查询不在当前组件作用域内的元素时。 - 推荐做法:虽然你可以直接调用
getByText
等方法,但使用screen
对象进行全局查询是 React Testing Library 推荐的做法,因为它更符合库的设计哲学和最佳实践。
注意:在 React Testing Library 的较新版本中,直接从 render
函数的返回结果中调用 getByText
等方法(如上例中的第一个示例)可能不是最佳实践,因为 render
函数现在通常只返回一个包含 container
和 baseElement
的对象,而不是直接提供查询方法。因此,你应该使用 screen
对象或 render
函数的返回结果中的 container
或 baseElement
(如果需要的话)来调用查询方法。然而,对于大多数用例来说,screen
对象提供了更简洁和全局的查询方式。