userEvent 与 fireEvent 的区别RTL 反对查询组件内部 state,鼓励用「用户可见的方式」查询:
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
test('点击按钮计数加一', async () => {
const user = userEvent.setup();
render(<Counter />);
await user.click(screen.getByRole('button', { name: /增加/i }));
expect(screen.getByText('1')).toBeInTheDocument();
});getByRole + name(最贴近读屏/键盘用户)getByLabelText(表单)getByText(文本)getByTestId(万不得已)优先 role/label 能顺带验证 34-组件无障碍 a11y 是否达标。
对 Suspense / 请求驱动的 UI,用 findBy*(返回 Promise)或 await waitFor:
const msg = await screen.findByText('加载完成'); // 自动重试直到出现或超时注意 act() 警告:RTL 的 render / userEvent 已自动包裹 act,避免手动 act 嵌套。
RTL 本身只管渲染与查询,断言库用 Jest 或 Vitest,jsdom / happy-dom 提供 DOM 环境。
RTL 让测试从「验证内部实现」转向「验证用户行为」,查询优先级天然促进可访问性。它是 React 组件测试的事实标准。