Trong quá khứ, chúng ta dùng Jest + Enzyme. Bây giờ là Vitest + React Testing Library (RTL).
1. Tại sao Vitest?
- Tốc độ: Nhanh gấp 3-5 lần Jest (nhờ Vite).
- Native ESM: Không cần cấu hình Babel/Transformer đau đầu như Jest.
- Watch Mode: Chạy test ngay tức thì khi save code.
2. Testing Philosophy: The Trophy 🏆
Đừng cố gắng đạt 100% Code Coverage bằng Unit Test nhỏ lẻ. Hãy theo mô hình Testing Trophy của Kent C. Dodds:
- Static Analysis (ESLint/TypeScript): Bắt lỗi cú pháp, typing ngay khi gõ code. (Cơ bản nhất).
- Integration Tests (Quan trọng nhất): Test sự kết hợp giữa các component. (Ví dụ: Form + Validation + Submit Button).
- Unit Tests: Test các hàm tiện ích (
utils/func.ts) hoặc hook phức tạp. - E2E Tests (Playwright/Cypress): Test luồng chính (Happy Path) trên trình duyệt thật.
Triết lý RTL: "Code test càng giống cách user sử dụng, thì test càng đáng tin cậy."
- KHÔNG:
wrapper.instance().state.isOpen(Test implementation detail). - CÓ:
screen.getByRole('button', { name: /open/i }).click()(Test behavior).
3. Setup Vitest + RTL cho Next.js
Cài đặt dependencies:
bash:
npm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/domTạo file vitest.config.ts:
ts:
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom', // Giả lập Browser
setupFiles: ['./vitest.setup.ts'],
globals: true, // Cho phép dùng describe, it, expect không cần import
},
});Tạo file vitest.setup.ts:
ts:
import '@testing-library/jest-dom'; // Thêm các matcher như toBeInTheDocument()
import { cleanup } from '@testing-library/react';
import { afterEach } from 'vitest';
// Tự động dọn dẹp biến DOM sau mỗi test case
afterEach(() => {
cleanup();
});Kết luận
- Chuyển sang Vitest ngay nếu có thể.
- Tập trung viết Integration Test (test component hoạt động với nhau) thay vì soi từng biến state bên trong component.