مش بيقلّد API خارجية
SuperTest بيبعت HTTP request للـ Node app أو server بتاعك، وبعدين يؤكد status وheaders وbody. لما تمرّر Express app، يقدر يربطه على port مؤقت، فمش محتاج تشغّل server منفصل.
SuperTest يختبر السيرفر اللي أنت كاتبه. MSW يعترض الطلب اللي كودك بيبعته لسيرفر تاني.افصل app عن listen
app.js
import express from "express";export const app = express();app.use(express.json());app.post("/users", (req, res) => { res.status(201).json({ id: 7, name: req.body.name });});server.js
import { app } from "./app.js";app.listen(3000);الفصل ده يخلي test تستورد app من غير ما تفتح port ثابت.
مع Vitest
pnpm add -D supertest @types/supertest
users.test.js
import request from "supertest";import { describe, expect, it } from "vitest";import { app } from "../src/app.js";describe("POST /users", () => { it("ينشئ مستخدم", async () => { const response = await request(app) .post("/users") .send({ name: "سعيد" }) .expect("Content-Type", /json/) .expect(201); expect(response.body).toEqual({ id: 7, name: "سعيد" }); });});SuperTest نفسه framework-agnostic؛ نفس request ينفع جوه Mocha أو Jest.
إيه اللي الاختبار ده بيثبته؟
بيعدّي على routing وbody parser والـ middleware والـ controller وتحويل response لـ HTTP. ده أقرب لـ integration test، حتى لو قاعدة البيانات fake.
مبيثبتش إن frontend عرف يتعامل مع الرد، ولا إن API خارجية شغالة، ولا إنه E2E كامل بمتصفح.
Session وcookies
لو السيناريو محتاج يحتفظ بالـ cookies بين requests، استخدم agent:
const agent = request.agent(app);await agent.post("/login").send({ email, password }).expect(204);await agent.get("/me").expect(200);
خلّصت الفصل لما
🧠 اختبر نفسك
١) ليه نفصل app.js عن server.js؟
عشان الاختبار يمرّر app لـ SuperTest من غير ما يشغّل port ثابت أو يبدأ process لوحده.
٢) اختبار SuperTest للـ route unit test؟
غالبًا integration test، لأنه بيعدّي على طبقات HTTP وmiddleware وrouting مع بعض.
٣) SuperTest بديل Vitest؟
لأ. Vitest يشغّل الاختبار؛ SuperTest ينشئ HTTP request ويختبر response.