Giới thiệu
Trong bài viết này, tôi sẽ hướng dẫn bạn cách kiểm thử API Server Side Rendering (SSR) của Next.js bằng cách sử dụng Playwright và Mock Service Worker (MSW). Việc tự động hóa kiểm thử tích hợp cho API SSR không phải là điều dễ dàng, nhưng với một chút kiến thức và sự hỗ trợ của các công cụ mạnh mẽ này, bạn có thể làm cho quá trình trở nên dễ dàng hơn. 🚀
Tóm tắt Playwright và MSW
Playwright
Playwright là một framework kiểm thử end-to-end được phát triển bởi Microsoft, cho phép bạn kiểm thử ứng dụng web trên nhiều trình duyệt khác nhau. Bạn có thể tìm hiểu thêm tại trang Playwright.
Mock Service Worker (MSW)
MSW là một thư viện giả lập API rất phổ biến, cho phép bạn mô phỏng các yêu cầu API trên cả trình duyệt và server (Node.js). Bạn có thể tìm hiểu thêm tại trang MSW.
Các vấn đề thường gặp khi kiểm thử API SSR với Playwright
Vấn đề 1: Khó khăn khi kiểm thử SSR
Playwright chủ yếu được thiết kế cho việc kiểm thử Client Side Rendering (CSR), vì vậy việc kiểm thử SSR với Next.js yêu cầu một số thiết lập bổ sung. Đặc biệt, bạn cần sử dụng một cổng khác (ví dụ: 3001) thay vì cổng mặc định (3000) của Next.js.
Giải pháp 1: Thiết lập cổng riêng và sử dụng MSW
Chúng ta sẽ sử dụng MSW để chặn yêu cầu API và trả về phản hồi giả lập. Điều này giúp bạn có thể kiểm thử các tình huống khác nhau mà không cần phải phụ thuộc vào API thực tế.
Thực hiện kiểm thử API SSR với Playwright và MSW
Bước 1: Cài đặt Next.js
Đầu tiên, bạn cần cài đặt Next.js bằng lệnh sau:
bash
npx create-next-app@latest my-app --yes
Bước 2: Chuyển đến thư mục dự án
bash
cd my-app
Bước 3: Cài đặt Playwright và MSW
Cài đặt Playwright:
bash
npm init playwright@latest
Cài đặt MSW:
bash
npm i msw --save-dev
Bước 4: Tạo cấu trúc mã nguồn
Tạo tệp page.tsx
typescript
/**
* Trang hiển thị Pokemon - Component Server Side đơn giản của Next.js
*
* Trang này lấy dữ liệu Pokemon và hiển thị nó trong một bố cục đơn giản.
* Trong quá trình kiểm thử, MSW sẽ chặn yêu cầu API và trả về dữ liệu giả lập dựa trên yêu cầu kiểm thử.
*
* Các khái niệm chính cho người mới:
* - Server-Side Rendering: Chạy trên server trước, sau đó gửi HTML đến trình duyệt.
* - Fetch API: Thực hiện các yêu cầu HTTP để lấy dữ liệu.
* - Xử lý lỗi: Hiển thị trang lỗi khi API gặp sự cố.
* - Tích hợp MSW: Kiểm thử có thể chuyển đổi giữa các Pokemon khác nhau hoặc kích hoạt lỗi.
*/
const DemoTitle = () => (
<h2 className="text-4xl font-bold text-blue-600 mb-6">
Cách kiểm thử API SSR Next.js
<br />
(Playwright + MSW)
</h2>
);
export default async function Home() {
try {
const response = await fetch("http://localhost:3001/api/v2/pokemon/charizard");
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const pokemon = await response.json();
return (
<div className="min-h-screen flex items-center justify-center p-4">
<div className="text-center">
<DemoTitle />
<h1 className="text-3xl font-bold mb-4">
{pokemon.name.charAt(0).toUpperCase() + pokemon.name.slice(1)}
</h1>
<img
src={pokemon.sprites.front_default}
alt={pokemon.name}
className="mx-auto mb-4 w-32 h-32"
/>
<p className="text-lg">Pokemon #{pokemon.id}</p>
</div>
</div>
);
} catch (error) {
return (
<div className="min-h-screen flex items-center justify-center p-4">
<div className="text-center">
<DemoTitle />
<h1 className="text-2xl font-bold text-red-600 mb-4">Lỗi</h1>
</div>
</div>
);
}
}
Bước 5: Thiết lập kiểm thử với Playwright
Bạn cần tạo một tệp kiểm thử mới, ví dụ example.spec.ts, với nội dung như sau:
typescript
import { test, expect } from "@playwright/test";
const setMockPokemon = async (
page: any,
mockType: "pikachu" | "eevee" | "error500" | null
) => {
const pokemon = mockType || "charizard";
await page.request.post("http://localhost:3001/api/switch-pokemon", {
data: { pokemon },
});
await page.waitForTimeout(100);
await page.goto("/");
await page.waitForLoadState("networkidle");
};
test.describe("Kiểm thử Pokemon cơ bản", () => {
test("Charizard (Pokemon mặc định)", async ({ page }) => {
await setMockPokemon(page, null);
await expect(page.locator("h1")).toContainText("Charizard");
await expect(page.locator("text=Pokemon #6")).toBeVisible();
});
test("Pikachu Mock", async ({ page }) => {
await setMockPokemon(page, "pikachu");
await expect(page.locator("h1")).toContainText("Pikachu");
await expect(page.locator("text=Pokemon #25")).toBeVisible();
});
test("Eevee Mock", async ({ page }) => {
await setMockPokemon(page, "eevee");
await expect(page.locator("h1")).toContainText("Eevee");
await expect(page.locator("text=Pokemon #133")).toBeVisible();
});
test("500 Lỗi", async ({ page }) => {
await setMockPokemon(page, "error500");
await expect(page.locator("h1")).toContainText("Lỗi");
});
});
Bước 6: Chạy các kiểm thử
Chạy máy chủ giả lập:
bash
npx tsx mock-server.ts
Chạy Next.js:
bash
npm run dev
Chạy kiểm thử Playwright:
bash
npx playwright test
Thực hành tốt nhất khi kiểm thử API
- Ghi chú rõ ràng: Đảm bảo rằng bạn ghi chú đầy đủ trong mã nguồn để người khác có thể hiểu được logic kiểm thử.
- Tách biệt kiểm thử: Thực hiện kiểm thử cho từng loại Pokemon để dễ dàng xác định lỗi.
- Sử dụng MSW hiệu quả: Đảm bảo bạn sử dụng MSW để mô phỏng nhiều tình huống khác nhau, không chỉ là lỗi 500.
Các cạm bẫy thường gặp
- Không thiết lập cổng đúng: Đảm bảo bạn đã chỉ định đúng cổng cho server để Playwright có thể kết nối.
- Quên xử lý lỗi: Xử lý các lỗi API là rất quan trọng để đảm bảo trải nghiệm người dùng tốt.
- Chạy kiểm thử song song: Cần cấu hình Playwright để chạy kiểm thử một cách tuần tự nếu bạn gặp vấn đề với trạng thái toàn cục.
Mẹo về hiệu suất
- Sử dụng
once: truekhi cần: Giúp giảm thiểu sự phức tạp trong mã khi sử dụng MSW. - Tối ưu hóa thời gian chờ: Giảm thời gian chờ giữa các yêu cầu để cải thiện tốc độ kiểm thử.
Kết luận
Việc kiểm thử API SSR của Next.js bằng Playwright và MSW có thể mang lại nhiều lợi ích cho phát triển ứng dụng của bạn. Hy vọng rằng với hướng dẫn này, bạn đã có thể thực hiện các bước cần thiết để thiết lập và kiểm thử API của mình một cách hiệu quả. Nếu bạn có bất kỳ câu hỏi nào, hãy để lại ý kiến của bạn bên dưới! 😊
Câu hỏi thường gặp (FAQ)
-
Tôi có thể sử dụng công cụ nào khác ngoài Playwright để kiểm thử không?
Có, bạn có thể sử dụng Cypress hoặc Selenium, nhưng mỗi công cụ có những ưu điểm và nhược điểm riêng. -
MSW có thể được sử dụng cho các loại dự án khác không?
Có, MSW có thể được sử dụng cho bất kỳ loại dự án nào cần giả lập API. -
Tôi có cần học thêm về Next.js không?
Có, kiến thức vững chắc về Next.js sẽ giúp bạn hiểu rõ hơn về cách hoạt động của SSR và cách kiểm thử hiệu quả hơn.