DEV Community

Alex Spinov
Alex Spinov

Posted on

MSW Has a Free API You're Not Using

Mock Service Worker (MSW) intercepts HTTP requests at the network level, giving you a complete API mocking solution that works in both browser and Node.js. Most developers only use it for basic request mocking.

What is MSW?

MSW intercepts requests using a Service Worker in the browser and custom interceptors in Node.js. Your application code makes real HTTP requests — MSW handles them before they leave your machine.

The Free APIs You're Missing

1. http.all() — Catch-All Request Handler

import { http, HttpResponse } from "msw";

export const handlers = [
  http.all("*/api/*", ({ request }) => {
    console.log(`${request.method} ${request.url}`);
    return HttpResponse.json(
      { error: "Not mocked yet" },
      { status: 501 }
    );
  }),
];
Enter fullscreen mode Exit fullscreen mode

Catch unmocked API calls during development. No more silent failures.

2. Network Behavior — Simulate Real Network Conditions

import { http, HttpResponse, delay } from "msw";

export const handlers = [
  http.get("/api/data", async () => {
    await delay(2000); // Simulate slow network
    return HttpResponse.json({ data: "loaded" });
  }),

  http.get("/api/flaky", async () => {
    await delay("real"); // Use realistic server timing
    if (Math.random() > 0.7) {
      return HttpResponse.error(); // Simulate network failure
    }
    return HttpResponse.json({ data: "maybe" });
  }),
];
Enter fullscreen mode Exit fullscreen mode

Test loading states, error boundaries, and retry logic with realistic network behavior.

3. GraphQL Handlers — Full GraphQL Mocking

import { graphql, HttpResponse } from "msw";

export const handlers = [
  graphql.query("GetUser", ({ variables }) => {
    return HttpResponse.json({
      data: {
        user: {
          id: variables.id,
          name: "John Doe",
          posts: [{ title: "Hello MSW" }],
        },
      },
    });
  }),

  graphql.mutation("CreatePost", ({ variables }) => {
    return HttpResponse.json({
      data: {
        createPost: { id: "new-post", ...variables },
      },
    });
  }),
];
Enter fullscreen mode Exit fullscreen mode

4. Life-Cycle Events — Observe All Network Traffic

const server = setupServer(...handlers);

server.events.on("request:start", ({ request }) => {
  console.log("Outgoing:", request.method, request.url);
});

server.events.on("request:match", ({ request }) => {
  console.log("Matched:", request.url);
});

server.events.on("request:unhandled", ({ request }) => {
  console.warn("UNHANDLED:", request.url);
});
Enter fullscreen mode Exit fullscreen mode

Debug your test network traffic. Catch requests that should be mocked but aren't.

5. Scenarios — Stateful API Mocking

const db = factory({
  user: {
    id: primaryKey(faker.string.uuid),
    name: faker.person.fullName,
    email: faker.internet.email,
  },
});

// Seed data
db.user.create({ name: "Admin" });
db.user.create({ name: "Regular User" });

export const handlers = [
  http.get("/api/users", () => {
    return HttpResponse.json(db.user.getAll());
  }),
  http.post("/api/users", async ({ request }) => {
    const data = await request.json();
    const user = db.user.create(data);
    return HttpResponse.json(user, { status: 201 });
  }),
  http.delete("/api/users/:id", ({ params }) => {
    db.user.delete({ where: { id: { equals: params.id } } });
    return new HttpResponse(null, { status: 204 });
  }),
];
Enter fullscreen mode Exit fullscreen mode

Full CRUD with in-memory database. Test entire user flows without a backend.

Getting Started

npm install msw --save-dev
npx msw init public/ --save
Enter fullscreen mode Exit fullscreen mode

Need data from any website delivered as clean JSON? I build production web scrapers that handle anti-bot, proxies, and rate limits. 77 scrapers running in production. Email me: Spinov001@gmail.com

Check out my awesome-web-scraping list for the best scraping tools and resources.

Top comments (0)