MSW vs Nock vs Polly.js
Choosing the right HTTP mocking library for JavaScript and TypeScript
When testing code that makes HTTP requests, you need a way to mock those requests without hitting real servers. Three popular JavaScript libraries tackle this problem with different approaches: MSW, Nock, and Polly.js.
Quick Comparison
| Feature | MSW | Nock | Polly.js |
|---|---|---|---|
| Interception Level | Service Worker (Browser) / Native modules (Node) | Node.js HTTP module | Multiple adapters (Fetch, XHR, Node HTTP) |
| Browser Support | ✅ Yes | ❌ No | ✅ Yes |
| Node.js Support | ✅ Yes | ✅ Yes | ✅ Yes |
| Record/Replay | ❌ No | ✅ Yes | ✅ Yes |
| Learning Curve | Medium | Low | Medium |
| Best For | Modern full-stack apps | Simple Node.js tests | Record/replay workflows |
MSW (Mock Service Worker)
Mock Service Worker intercepts requests at the network level using Service Workers in browsers and native Node.js modules. No server setup required, works in any framework.
Pros
- Works in both browser and Node.js with the same API
- Uses Service Workers for network-level interception (no patching)
- Great for testing at a higher level (closer to production)
- Can be used in development for local API mocking
Cons
- Requires Service Worker setup in browser tests
- No built-in record/replay functionality
- Steeper learning curve than Nock
Example Usage
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
const server = setupServer(
http.get('/api/user', () => {
return HttpResponse.json({ id: 1, name: 'John' })
})
)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())Nock
HTTP server mocking and expectations library for Node.js. Intercepts requests at the Node.js HTTP module level, perfect for unit testing external API calls.
Pros
- Simple, straightforward API
- Built-in recording mode for capturing real API responses
- Powerful request matching and assertions
- Battle-tested and widely adopted
Cons
- Node.js only (no browser support)
- Intercepts at the HTTP module level (patching)
- Can interfere with other HTTP-based tools
Example Usage
import nock from 'nock'
nock('https://api.example.com')
.get('/user/1')
.reply(200, { id: 1, name: 'John' })
// Your test code here
// Nock automatically intercepts matching requestsPolly.js
Record, replay, and stub HTTP interactions. Built by Netflix, works with multiple adapters including Fetch, XHR, and Node HTTP.
Pros
- Built by Netflix for production use
- Powerful record/replay capabilities
- Works in both browser and Node.js
- Multiple adapters for different environments
Cons
- More complex setup than Nock or MSW
- Less actively maintained (Netflix open-sourced it)
- Larger API surface to learn
Example Usage
import { Polly } from '@pollyjs/core'
import FetchAdapter from '@pollyjs/adapter-fetch'
import LocalStoragePersister from '@pollyjs/persister-local-storage'
Polly.register(FetchAdapter)
Polly.register(LocalStoragePersister)
const polly = new Polly('My Test', {
adapters: ['fetch'],
persister: 'local-storage'
})
// Polly records and replays automaticallyWhich Should You Choose?
Choose MSW if...
- You're building a modern React, Vue, or Angular app
- You want the same mocking solution for both browser and Node.js
- You prefer network-level interception without patching
- You want to use mocks in development (not just tests)
Choose Nock if...
- You're only testing Node.js code
- You want the simplest possible API
- You need powerful request matching and recording
- You're working on a backend service or API
Choose Polly.js if...
- You need sophisticated record/replay workflows
- You're working in a complex environment with many adapters
- You want to capture real API traffic and replay it in tests
- You don't mind a more complex setup process