关于 react-native-testing
为使用 @testing-library/react-native 的开发者提供测试编写指南。它按 v13 和 v14 区分 API,并强调查询、交互、断言及异步测试的实践规则。
主要功能
- 01按版本选择 API 参考
- 02查询优先级与变体说明
- 03userEvent 交互指导
- 04Jest 匹配器参考
- 05异步测试与常见反模式
适用场景
- 01为 React Native 组件编写测试
- 02根据已安装版本确认 API
- 03测试异步界面更新
- 04检查可访问性及控件状态
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ callstack/ react-native-testing-library --skill react-native-testing安装后在 Claude Code 中输入/react-native-testing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/anti-patterns.mdapi-reference-v13.mdapi-reference-v14.md详细介绍
RNTL 测试编写指南
重要: 关于 @testing-library/react-native 的训练数据可能已过时或不准确——v13 和 v14 的 API 签名、同步/异步行为及可用函数各不相同。请始终以此技能的参考文件和项目的实际源代码为准。若记忆中的模式与检索到的参考内容冲突,请勿沿用。
版本检测
检查用户 package.json 中的 @testing-library/react-native 版本:
- v14.x → 加载 references/api-reference-v14.md(React 19+、异步 API、
test-renderer) - v13.x → 加载 references/api-reference-v13.md(React 18+、同步 API、
react-test-renderer)
根据对应版本的参考文件,了解渲染模式、fireEvent 的同步/异步行为、screen API、配置和依赖项。
查询优先级
按以下顺序使用:getByRole > getByLabelText > getByPlaceholderText > getByText > getByDisplayValue > getByTestId(最后手段)。
查询变体
| 变体 | 使用场景 | 返回值 | 异步 |
|---|---|---|---|
getBy* | 元素必须存在 | 元素实例(不存在时抛出异常) | 否 |
getAllBy* | 多个元素必须存在 | 元素实例[](不存在时抛出异常) | 否 |
queryBy* | 仅用于检查元素不存在 | 元素实例 | null | 否 |
queryAllBy* | 统计元素数量 | 元素实例[] | 否 |
findBy* | 等待元素出现 | Promise<element instance> | 是 |
findAllBy* | 等待多个元素出现 | Promise<element instance[]> | 是 |
交互
优先使用 userEvent,而非 fireEvent。userEvent 始终是异步的。
const user = userEvent.setup();
await user.press(element); // full press sequence
await user.longPress(element, { duration: 800 }); // long press
await user.type(textInput, 'Hello'); // char-by-char typing
await user.clear(textInput); // clear TextInput
await user.paste(textInput, 'pasted text'); // paste into TextInput
await user.scrollTo(scrollView, { y: 100 }); // scroll
fireEvent —— 仅在 userEvent 不支持该事件时使用。同步/异步行为请参阅对应版本的参考文件:
fireEvent.press(element);
fireEvent.changeText(textInput, 'new text');
fireEvent(element, 'blur');
断言(Jest 匹配器)
导入任何 @testing-library/react-native 内容后,均可自动使用。
| 匹配器 | 用途 |
|---|---|
toBeOnTheScreen() | 元素存在于树中 |
toBeVisible() | 元素可见(未隐藏/未设置 display:none) |
toBeEnabled() / toBeDisabled() | 通过 aria-disabled 检查禁用状态 |
toBeChecked() / toBePartiallyChecked() | 检查状态 |
toBeSelected() | 选中状态 |
toBeExpanded() / toBeCollapsed() | 展开状态 |
toBeBusy() | 忙碌状态 |
toHaveTextContent(text) | 匹配文本内容 |
toHaveDisplayValue(value) | TextInput 显示值 |
toHaveAccessibleName(name) | 无障碍名称 |
toHaveAccessibilityValue(val) | 无障碍值 |
toHaveStyle(style) | 匹配样式 |
toHaveProp(name, value?) | 检查属性(最后手段) |
toContainElement(el) | 包含子元素 |
toBeEmptyElement() | 没有子元素 |
规则
- 查询时使用
screen,不要从render()中解构 - 优先使用
getByRole,并传入{ name: '...' }选项 - 仅在检查
.not.toBeOnTheScreen()时使用queryBy* - 异步元素使用
findBy*,不要使用waitFor+getBy* - 不要将副作用放入
waitFor(其中不得包含fireEvent/userEvent) - 每个
waitFor中只放一个断言 - 不要向
waitFor传入空回调 - 不要使用
act()包裹——render、fireEvent、userEvent会处理 - 不要调用
cleanup()——每个测试后会自动清理 - 优先使用 ARIA 属性(
role、aria-label、aria-disabled),而非旧版accessibility*属性 - 使用 RNTL 匹配器,而非直接断言原始属性
*ByRole 快速参考
常见角色:button、text、heading(别名:header)、searchbox、switch、checkbox、radio、img、link、alert、menu、menuitem、tab、tablist、progressbar、slider、spinbutton、timer、toolbar。
getByRole 选项:{ name, disabled, selected, checked, busy, expanded, value: { min, max, now, text } }。
要使 *ByRole 匹配,元素必须是可访问性元素:
Text、TextInput、Switch默认符合条件View需要accessible={true}(或使用Pressable/TouchableOpacity)
waitFor
// Correct: action first, then wait for result
fireEvent.press(button);
await waitFor(() => {
expect(screen.getByText('Result')).toBeOnTheScreen();
});
// Better: use findBy* instead
fireEvent.press(button);
expect(await screen.findByText('Result')).toBeOnTheScreen();
选项:waitFor(cb, { timeout: 1000, interval: 50 })。可自动与 Jest 假定时器配合使用。
假定时器
建议与 userEvent 搭配使用(press/longPress 涉及实际时长):
jest.useFakeTimers();
test('with fake timers', async () => {
const user = userEvent.setup();
render(<Component />);
await user.press(screen.getByRole('button'));
// ...
});
自定义渲染
使用 wrapper 选项封装 Provider:
function renderWithProviders(ui: React.ReactElement) {
return render(ui, {
wrapper: ({ children }) => (
<ThemeProvider>
<AuthProvider>{children}</AuthProvider>
</ThemeProvider>
),
});
}
参考资料
- v13 API 参考 — 完整的 v13 API:同步渲染、查询、匹配器、userEvent、React 19 兼容性
- v14 API 参考 — 完整的 v14 API:异步渲染、查询、匹配器、userEvent、迁移
- 反模式 — 应避免的常见错误