Mock Service Worker (MSW) lets developers build and test the frontend without waiting for a real backend. It simulates API responses directly in the browser, making development smoother and more predictable.

Why MSW Matters

MSW helps in situations when:

  • The backend is not ready yet.
  • Local access to the real backend is restricted.
  • You need stable, predictable APIs for tests.
  • You want realistic mocks without maintaining a separate server.

MSW intercepts requests at the network level using a Service Worker. It behaves like a real backend: it receives requests, inspects them, and responds with mock data. Your frontend continues using fetch, axios, and REST endpoints exactly as in production.

How MSW Works

  1. You create request handlers.
  2. A Service Worker intercepts matching requests.
  3. The handler returns a mock response.
  4. In production, the worker is disabled, and real requests flow normally.

MSW is based on real browser technologies, so responses mimic real network behavior including delays, headers, cookies, and more.

Installation

bash
npm install msw@latest --save-dev

Initialize MSW:

bash
npx msw init ./public --save

This command creates mockServiceWorker.js in the public folder where the app can register it.

Creating Request Handlers

Create src/mocks/handlers.js:

js
import { http, HttpResponse } from 'msw';

const coursesResolver = () => {
  return HttpResponse.json([
    {
      id: '0',
      title: 'Introduction to Web Development with Modern Frameworks',
      description:
        'Learn the basics of web development using the latest tools and frameworks',
      instructor: '@WebDevMaster',
    },
    {
      id: '1',
      title: 'Mastering CSS Grid and Flexbox',
      description: 'Comprehensive guide to modern CSS layout techniques',
      instructor: '@CSSGuru',
    },
  ]);
};

export const handlers = [
  http.get('/api/courses', coursesResolver),
];

Setting Up the Browser Worker

Create src/mocks/browser.js:

js
import { handlers } from './handlers';
import { setupWorker } from 'msw/browser';

export const worker = setupWorker(...handlers);

In your application entrypoint:

jsx
async function enableMocking() {
  if (process.env.NODE_ENV !== 'production') {
    const { worker } = await import('./mocks/browser');
    return worker.start({ onUnhandledRequest: 'bypass' });
  }
}

Advanced Example

MSW supports:

  • URL params
  • Delays
  • Multiple HTTP methods
  • JSON body parsing
  • Error responses

Extended example:

js
import { delay, http, HttpResponse } from 'msw';

const educationalCourses = [
  {
    id: '1',
    title: 'Fundamentals of JavaScript',
    description: 'A complete introduction to JavaScript programming.',
    instructor: 'Sarah Johnson',
    duration: '8 weeks',
    enrollmentStatus: 'Open',
    createdAt: '2025-03-10T10:00:00Z',
  },
];

export const handlers = [
  http.get('/api/education/courses', async () => {
    await delay(500);
    return HttpResponse.json(educationalCourses);
  }),

  http.get('/api/education/courses/:id', async ({ params }) => {
    const item = educationalCourses.find(c => c.id === params.id);
    return item
      ? HttpResponse.json(item)
      : new HttpResponse(null, { status: 404 });
  }),

  http.post('/api/education/courses', async ({ request }) => {
    const newCourse = await request.json();
    const course = {
      id: String(educationalCourses.length + 1),
      ...newCourse,
      enrollmentStatus: 'Open',
      createdAt: new Date().toISOString(),
    };
    educationalCourses.push(course);
    return HttpResponse.json(course, { status: 201 });
  }),
];

Using MSW in Tests

js
import { setupServer } from 'msw/node';
import { handlers } from './handlers';

export const server = setupServer(...handlers);

Testing:

js
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

Conclusion

MSW allows you to:

  • Develop frontend features before the backend is ready.
  • Test user flows reliably.
  • Simulate realistic API behavior.
  • Avoid maintaining a separate mock server.
  • Use the same API endpoints in development and production.

To explore advanced features, visit the official documentation:
mswjs docs