الـ HTTP · فصل ٦

MSW — اعترض الشبكة بدل ما تغيّر كودك

setupServer · setupWorker · http · HttpResponse · handlers
🎯 الهدف: تعمل API mocks على مستوى الشبكة وتعيد استخدام نفس handlers في الاختبار والمتصفح.

الفكرة

بدل ما تعمل mock لـ fetch وتختبر إنك ناديتها، MSW يعترض request حقيقية عند network boundary ويرجع response متحكم فيها. كود التطبيق يفضل بينادي fetch عادي.

في المتصفح يستخدم Service Worker. في Node tests يستخدم interceptors من خلال setupServer.

Handler واحدة

test/handlers.js
import { http, HttpResponse } from "msw";export const handlers = [  http.get("https://api.example.com/user", () => {    return HttpResponse.json({ id: 7, name: "سعيد" });  }),];

مع Vitest في Node

test/server.js
import { setupServer } from "msw/node";import { handlers } from "./handlers.js";export const server = setupServer(...handlers);
test/setup.js
import { afterAll, afterEach, beforeAll } from "vitest";import { server } from "./server.js";beforeAll(() => server.listen({ onUnhandledRequest: "error" }));afterEach(() => server.resetHandlers());afterAll(() => server.close());

onUnhandledRequest: "error" يمنع test من الخروج للإنترنت بالغلط. وresetHandlers يشيل overrides الخاصة بكل test.

جرّب error path

import { http, HttpResponse } from "msw";server.use(  http.get("https://api.example.com/user", () => {    return HttpResponse.json(      { message: "service unavailable" },      { status: 503 },    );  }),);

كده تقدر تختبر loading وempty وerror وretry من غير backend شغالة.

في المتصفح

نفس handlers تدخل على:

import { setupWorker } from "msw/browser";import { handlers } from "./handlers.js";export const worker = setupWorker(...handlers);

وده مفيد للـ local development، demos، وcomponent tests في browser. متشغّلوش في production بالغلط.

MSW ولا mock fetch؟

الحالةالأنسب
دالة صغيرة واخدة fetcher كـ argumentfake function بسيطة
component أو service بيعمل HTTPMSW
عايز نفس mock في Node والمتصفحMSW
عايز تتأكد من URL وmethod وbody الحقيقيينMSW

خلّصت الفصل لما

🧠 اختبر نفسك
١) ليه MSW أقرب لسلوك التطبيق من vi.mock للـ API module؟
لأن التطبيق ينفّذ request عادية، والاعتراض يحصل عند network boundary بدل استبدال module من جوه.
٢) server.resetHandlers() بتعمل إيه؟
تشيل overrides اللي اتضافت أثناء test وترجع للـ handlers الأصلية، عشان الاختبارات متأثرش على بعض.
٣) MSW تثبت إن backend الحقيقية مطابقة؟
لأ. هي mock للـ network؛ محتاج contract أو integration tests إضافية للثقة في backend الحقيقية.