- Introduction
- Quick start
- Philosophy
- Comparison
- Default behaviors
- Limitations
- Debugging runbook
- FAQ
- Mocking HTTP
- Mocking GraphQL
- Mocking WebSocket
- Integrations
- API
- CLI
- Best practices
- Recipes
Default behaviors
Important default behaviors of Mock Service Worker.
Default passthrough
MSW embraces a network-first approach, which means that it will not interfere with the network unless you explicitly say so in your handlers.
Intercepting WebSockets, however, is mock-first due to the limitations of their specification.
Handler fallthrough
Every intercepted request “falls through” the list of your handlers, looking for the first matching handler to return an instruction on how to handle the request (mock response, response-patch, passthrough, do nothing). A single request may match multiple handlers at the same time but only one handler can be responsible for handling it.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/user', () => console.log('One')),
http.get('/user', () => HttpResponse.json({ name: 'John' })),
http.get('/user', () => console.log('Three')),
]
In the example above, given an outgoing
GET /user
request, you will see the"One"
string printed to the console and then receive the mocked JSON response as defined in the second handler. You will not see the"Three"
string because the third handler is never reached (i.e. request already handled).
You can use fallthrough to a great effect to layer your network behaviors. See Network behavior overrides.
Handler order sensitivity
Derived from the fallthrough behavior, handlers are sensitive to the order in which they are defined. MSW executes them left-to-right, starting from handler overrides, if any, since those are prepended to the list of handlers.
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node
export const handlers = [
http.get('/user', () => console.log('One')),
http.get('/user', () => console.log('Two')),
http.get('/user', () => console.log('Three')),
]
const server = setupServer(...handlers)
server.listen()
server.use(
http.get('/user', () => console.log('Override one')),
)
Given an outgoing GET /user
request, this is what you will see in the console:
Override one
One
Two
Three
The request itself will be performed as-is according to the default passthrough since none of the handlers above has handled it.
Use the handler order sensitivity to differentiate between ambiguous request matches:
export const handlers = [
// By placing a more specific request predicate first,
// the "GET /user/messages" request will be handled
// properly, despite it also matching a more permissive
// "/user/*" handler below.
http.get('/user/messages', messagesResolver)
http.get('/user/*', resolverOne),
]