If you write frontend tests, you’ve probably hit Mock Service Worker (MSW). It’s the go-to library for intercepting requests inside the browser and Node, and for unit and component tests it’s hard to beat. This guide explains what MSW does well, where it stops scaling, and when a hosted API mocking platform makes more sense.
What is Mock Service Worker?
Mock Service Worker is a JavaScript library that intercepts network requests at the source. In the browser it registers a Service Worker that catches outgoing fetch and XMLHttpRequest calls. In Node, it patches the request layer so the same handlers run in Jest or Vitest. You write request handlers that match a method and path, then return whatever response you want.

The design is clever. Your application code keeps calling the real network APIs. MSW sits in the middle and answers, so you don’t stub fetch or swap your HTTP client. The same mock definitions work in tests and in a running dev build, which is why so many React and Vue teams reach for it. You can dig into the MSW source on GitHub to see how the interception layer works.
A typical handler looks like this:
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/api/users/:id', ({ params }) => {
return HttpResponse.json({ id: params.id, name: 'Ada Lovelace' })
}),
]
That’s the whole appeal. The mock lives next to your code, it’s version-controlled with your tests, and it runs wherever your JavaScript runs.
Where MSW shines
MSW is a strong fit when the mock and the consumer live in the same codebase. A few cases where it’s genuinely the right tool:
- Component and unit tests. Render a component, let it fire its real requests, and return canned data. No test doubles to wire up. If you’re comparing it to spying on the client directly, see how this differs from a Jest mock of an API call.
- Local frontend development. Build the UI before the backend exists. Toggle handlers to simulate loading, errors, or empty states on demand.
- Deterministic CI. Tests don’t touch a live server, so they don’t flake on network conditions or shared staging data.
- One language, one team. When the people writing the mock are the people consuming it, keeping handlers in the repo is the simplest path.
If that describes your situation, you probably don’t need anything else. MSW is free, open source, and built for exactly this.
Where MSW starts to strain
The same thing that makes MSW great in a single repo, mocks that live as code in that repo, is what limits it once more people get involved. Here’s where teams tend to outgrow it.
Non-JavaScript consumers
MSW handlers are JavaScript. If your mobile team writes Swift or Kotlin, or your backend integration tests run in Go or Python, they can’t import your handlers. They’d need their own mocks, which drift from yours. A language-agnostic mock server that speaks HTTP over a real URL works for every client, no matter the language.
Shared, always-on mocks
MSW runs inside a process. There’s no shared URL a QA engineer, a designer, or a partner team can hit from their own machine. The moment you want one endpoint that several people use at once, you need a hosted mock server with a stable address, not a Service Worker bound to one browser tab.
Design-first and schema-driven workflows
If you design APIs in OpenAPI before writing code, you want mocks generated from the spec automatically, so the mock can’t disagree with the contract. MSW expects you to hand-write handlers. Generating mocks straight from a schema is a different model. You can read more on that approach in this guide to API mocking and the patterns around it.
Realistic, dynamic data at scale
MSW returns whatever your handler codes. For lifelike data across many fields, you write that logic yourself. Platforms that wire in faker-style generation and field-name inference give you realistic responses without hand-rolling each one.
MSW vs a full API mocking platform
Here’s an honest side-by-side. Neither column is “better” in the abstract; they solve different problems.
| Capability | Mock Service Worker | Hosted API platform (e.g. Apidog) |
|---|---|---|
| Runs inside JS unit/component tests | Yes, native | No, it’s not a JS test library |
| Language-agnostic over HTTP | No (JS only) | Yes, any client |
| Shared URL for whole team | No | Yes, hosted mock server |
| Generate mocks from OpenAPI | Manual | Automatic from schema |
| Smart/dynamic data generation | Hand-coded | Built in |
| Lives in your repo with tests | Yes | Stored in shared project |
| Cost | Free, open source | Free tier + paid plans |
The takeaway: MSW is the right call for frontend tests and local development. A platform like Apidog is the right call when the mock has to be shared, language-neutral, or driven by a spec.
Apidog as the complement, not the replacement
To be clear, Apidog isn’t a drop-in for MSW inside Jest or Vitest. It isn’t a JavaScript library you import into a test file. Treat it as the layer above your unit tests, the place where mocks become a shared, language-agnostic resource for the whole team.
Here’s what that looks like in practice. You design or import an API in Apidog, and it generates a mock endpoint automatically from the schema. The mock gets a real URL your frontend, mobile, and QA teammates can all call. Apidog fills responses with realistic data by inferring from field names, so a field called email returns an email and createdAt returns a date. You can also write custom rules when you need a specific 500 response or a particular edge case.

Because the mock comes from the same schema as your design and tests, it stays in sync with the contract. That’s the part hand-written handlers can’t guarantee. If you want to see how schema-to-mock generation compares across tools, this roundup of the best API mocking tools puts the options next to each other.

A practical split many teams land on:
- Keep MSW for component and unit tests inside the frontend repo.
- Use a hosted mock for cross-team integration, demos, and any non-JS consumer.
You’re not picking one. You’re using each where it fits. Download Apidog if you want to try the hosted side alongside your existing MSW setup.
Other MSW alternatives worth knowing
MSW isn’t the only mocking library, and a platform isn’t your only option. Depending on your stack:
- Mockoon is a desktop app for spinning up local mock servers fast, with a GUI instead of code.
- WireMock is a Java-based mock server, strong for JVM teams and contract testing.
- Prism by Stoplight generates a mock straight from an OpenAPI file via the command line.
- json-server turns a JSON file into a quick REST API for prototyping.
Each trades something. WireMock and Prism lean toward backend and contract work; Mockoon and json-server lean toward fast local setup. If your blocker is specifically “MSW can’t help my non-JS teammates,” any HTTP-based mock server solves it. For a broader frontend angle, see how teams handle mocking APIs in React with Axios.
Frequently asked questions
Is MSW free?
Yes. Mock Service Worker is open source under the MIT license and free to use in any project, commercial or not. You only start paying when you move to a hosted platform for shared mocks, and tools like Apidog include a free tier for that too.
Can Apidog replace MSW in my unit tests?
No, and you shouldn’t try to make it. MSW intercepts requests inside your JavaScript test runner. Apidog is a hosted platform, not an importable library, so it can’t sit inside Jest or Vitest the way MSW does. Use Apidog for shared, cross-team, or schema-driven mocks instead. If you’re focused purely on the test-runner side, this walkthrough on how to mock API calls covers the in-code approaches.
Does MSW work in Node, or only the browser?
Both. In the browser MSW uses a Service Worker. In Node it patches the request layer so the same handlers run in Jest, Vitest, or any Node test environment. That dual mode is one of its biggest strengths for full-stack JS teams.
When should I switch from MSW to a hosted mock server?
Switch, or rather add one, when the mock needs to be shared. The clearest signals: a non-JavaScript client needs it, multiple people need the same stable URL, or you design APIs spec-first and want mocks generated from OpenAPI automatically.
Conclusion
MSW is excellent at what it’s built for: intercepting requests inside JavaScript for frontend and unit tests. It doesn’t try to be a shared, hosted, language-agnostic mock, and that’s fine. When your mocks need to leave the repo, when other languages or other teams need them, or when you want them generated from a spec, that’s the moment to add a full platform alongside it.
Apidog handles the shared, schema-driven side: a hosted mock server with a real URL, automatic mocks from your OpenAPI design, and realistic data out of the box. Keep MSW where it’s strong, and let Apidog cover everything past the edge of your test runner. Download Apidog and point your frontend at a shared mock to see the difference.



