DEV Community

Cover image for Elevate your React project to the next level using MSW mocking flow
Nikola Perišić
Nikola Perišić

Posted on

Elevate your React project to the next level using MSW mocking flow

Introduction

In this blog, I will walk you through why MSW mocking is useful, and how to implement it in your React.js application.


The problem

Let’s say you’re building a feature that consumes data from a backend API, but:

  • The backend isn’t ready yet
  • You’re having CORS issues, and the backend developer took a sick day :(
  • You’re on a tight deadline

In most cases, you might just mock the data using a single constant.

But there’s a better approach.

The Solution: Mock Service Worker (MSW)

MSW works by intercepting actual network requests at the service worker level. What does that means?

  • Your application thinks it’s communicating with a real API
  • Your mocks work both in the browser and in tests
  • You can simulate everything from successful responses to errors, timeouts, and more. This is very important

I can tell that it’s the closest thing to working with the real thing, without actually depending on it.

Diagram

MSW flow diagram

In the diagram above, we can identify total of three actors:

  1. Browser -> Let’s imagine you have a page called PrivacyPolicy.jsx. This component uses a custom hook or a direct fetch/axios call to request data from the endpoint /v1/privacy-policy. In default scenario, this request would hit backend API URL, but with our approach, this request is intercepted before it ever leaves the browser and it does not hit backend.
  2. MSW service worker -> This worker is registered and running in the browser. It listens to all requests coming from you application. When your React app makes a request to /v1/privacy-policy, the MSW service worker intercepts it and checks if a corresponding mock handler is defined. It does this by referring to your mock definition file (commonly named handlers.js).

  3. Handlers.js -> This file contains a list of all mocked endpoints and how they should respond. If a matching handler is found, the service worker returns the mocked response as if it came from the real server. Your React component receives the data and renders the UI.

Key benefits

  1. Fully isolated UI development - With MSW, your frontend development is no longer blocked by backend availability.

  2. Easier error state simulation (timeout, 500 errors, etc.) -> Simulating edge cases is crucial for building resilient UIs. MSW makes easy to:

  • Mock slow network responses (e.g. ctx.delay(3000)) to test loading states.

  • Simulate server errors (e.g. 500, 401, 404) to test error handling.

  • Validate how your UI reacts to flaky connections, unauthorized access, or unexpected data.

  1. Shared, reusable mocks for testing and Storybook

Hot to implement it?

  1. Install the package
npm i msw
Enter fullscreen mode Exit fullscreen mode
  1. Define your handlers Create a mocks/handlers.js file
// handlers.js
import { http, HttpResponse } from 'msw';

export const handlers = [
  http.get(`${API_URL}/v1/privacy-policy`, async () => {
    return HttpResponse.json({
      documentBody: `
        <h1>Privacy Policy</h1>
        <p>We value your privacy and handle your data responsibly.</p>
      `
    });
  }),
];
Enter fullscreen mode Exit fullscreen mode
  1. Setup the service worker

Create a mocks/browser.js file

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

export const worker = setupWorker(...handlers);
Enter fullscreen mode Exit fullscreen mode
  1. Modify your .env file
VITE_ENABLE_MOCKING=true
Enter fullscreen mode Exit fullscreen mode
  1. Modify your main.jsx file (just add "enableMocking" method)
// main.tsx
// imports {}

async function enableMocking() {
  if (import.meta.env.VITE_ENABLE_MOCKING !== 'true') return;
  const { worker } = await import('./mocks/browser');

  return worker.start();
}

enableMocking().then(() => {
  const rootElement = document.getElementById('root');
  if (!rootElement) throw new Error('Root element not found');

  createRoot(rootElement).render(
    <StrictMode>
    </StrictMode>
  );
});
Enter fullscreen mode Exit fullscreen mode

Note: If you plan to use it also in test environment, be sure to create a mocks/node.js file:

// mocks/server.jsx

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

export const server = setupServer(...handlers);
Enter fullscreen mode Exit fullscreen mode

For more informations, you can check out official MSW documentation.


Bonus 🎁

I’m sharing template starter for handlers.js file that I use in my projects.

It includes mocked api endpoints, use of zod schemas for validation, delays and much more!


Connect with me

GitHub, LinkedIn, Medium

Top comments (2)

Collapse
 
kettanaito profile image
Artem Zakharchenko

Thanks for this writeup, Nikola!
If I may, one small correction to the diagram would be to place the "handlers" part within your app's box (because that's where they are). So that the request flow is this:

  1. Your app makes a request in the browser.
  2. Service Worker catches the request (separate thread). Asks the client how to handle it.
  3. The client instructs the worker how to handle the request.
  4. The worker handles the request and sends the response back to the client.

That is only if you want to approach this diagram from a strictly technical perspective. As a general illustration, yours works fine.

Collapse
 
nathan_tarbert profile image
Nathan Tarbert

Yessir, this kind of hands-on stuff for React just makes my life so much easier.