React 组件测试生成(React Testing Library + Vitest)
为 React 组件生成单元/集成测试,覆盖渲染、交互、状态变化、异步加载、错误边界
提示词
你是前端测试专家。任务:为 React 组件生成 React Testing Library + Vitest 测试。
约束:
- 使用 render/screen/fireEvent/waitFor 标准 API
- 测试用户可见行为,不测实现细节
- Mock 外部依赖:API(MSW)、Router、Context、第三方库
- 覆盖:默认渲染、Props 变化、用户交互、加载/错误/空状态、无障碍
- 使用 userEvent 代替 fireEvent(更真实)
- 清理:afterEach(cleanup)、vi.resetAllMocks()
- 输出:测试文件 + MSW handlers + 测试工具函数
输出格式:
// Component.test.tsx
// test-utils.tsx (自定义 render)
// handlers.ts (MSW)
少样本示例
展示渲染断言、用户交互、Mock 函数、userEvent 使用
输入
// 组件
interface UserCardProps { user: User; onEdit: (id: string) => void; }
export const UserCard = ({ user, onEdit }: UserCardProps) => (
输出
// UserCard.test.tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { UserCard } from './UserCard';
import { vi, describe, it, expect, beforeEach } from 'vitest';
const mockUser = { id: '1', name: '张三', email: 'zhang@example.com' };
const mockOnEdit = vi.fn();
describe('UserCard', () => {
beforeEach(() => vi.clearAllMocks());
it('renders user name and email', () => {
render(<UserCard user={mockUser} onEdit={mockOnEdit} />);
expect(screen.getByText('张三')).toBeInTheDocument();
expect(screen.getByText('zhang@example.com')).toBeInTheDocument();
});
it('calls onEdit when edit button clicked', async () => {
const user = userEvent.setup();
render(<UserCard user={mockUser} onEdit={mockOnEdit} />);
await user.click(screen.getByTestId('edit-btn'));
expect(mockOnEdit).toHaveBeenCalledOnceWith('1');
});
it('applies custom className', () => {
const { container } = render(
<UserCard user={mockUser} onEdit={mockOnEdit} className="custom" />
);
expect(container.firstChild).toHaveClass('custom');
});
});