- Introduction
- Getting started
- Philosophy
- Comparison
- Limitations
- Debugging runbook
- FAQ
- Basics
- Concepts
- Network behavior
- Integrations
- API
- CLI
- Best practices
- Recipes
- Cookies
- Query parameters
- Response patching
- Polling
- Streaming
- Network errors
- File uploads
- Responding with binary
- Custom worker script location
- Global response delay
- GraphQL query batching
- Higher-order resolver
- Keeping mocks in sync
- Merging Service Workers
- Mock GraphQL schema
- Using CDN
- Using custom "homepage" property
- Using local HTTPS
Mocking responses
Learn how to mock HTTP responses.
Basics
Mock Service Worker respects the WHATWG Fetch API specification, which means that the mocked responses you construct are the same responses you would receive when making a fetch
call. If you are comfortable with the Response
class, you can skip everything past this section—you know how to declare responses already.
To respond to an intercepted request, return a valid Response
instance from the matching request handler:
import { http } from 'msw'
export const handlers = [
// Intercept the "GET /resource" request.
http.get('/resource', () => {
// And respond with a "text/plain" response
// with a "Hello world!" text response body.
return new Response('Hello world!')
}),
]
You don’t need to import the Response
class because it’s a part of the global Fetch API in the browser and modern versions of Node.js (v17+). The library supports any variations of the Response
instances, including shorthand responses created via methods like Response.json()
or Response.error()
.
Using HttpResponse
class
Although you can use plain Fetch API responses, it’s highly recommended you use the custom HttpResponse
class provided by the library. There are two reasons to prefer HttpResponse
over the native Response
:
- The
HttpResponse
class encapsulates useful shorthand methods for declaring responses, likeHttpResponse.json()
,HttpResponse.xml()
,HttpResponse.formData()
, etc. - Unlike the native
Response
class, theHttpResponse
class enables support for mocking response cookies by setting theSet-Cookie
header on the mocked response.
Here’s the same GET /resource
handler but using the HttpResponse
class:
// 1. Import the "HttpResponse" class from the library.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/resource', () => {
// 2. Return a mocked "Response" instance from the handler.
return HttpResponse.text('Hello world!')
}),
]
HttpResponse
is 100% compatible with the nativeResponse
class. Under the hood,HttpResponse
returns a plain Fetch APIResponse
instance.
Mocking status code and text
Provide the status
and/or statusText
property in the response initializer object to specify a mocked response status or response status code, respectively.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/apples', () => {
return new HttpResponse(null, {
status: 404,
statusText: 'Out Of Apples',
})
}),
]
Mocking headers
Provide the headers
property in the response initializer object to specify mocked response headers.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.post('/auth', () => {
return new HttpResponse(null, {
headers: {
'Set-Cookie': 'mySecret=abc-123',
'X-Custom-Header': 'yes',
},
})
}),
]
Learn more about constructing Headers.
Mocking body
You can respond to requests with various response body types: String
, Blob
, FormData
, ReadableStream
, and others (see Fetch API Response
for supported response body types).
Below, let’s take a look at how to mock some of the most common HTTP response bodies.
Text responses
The most basic response in HTTP is a text response. Provide the text string you wish to respond with as an argument to the HttpResponse
constructor to create a mocked text response:
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/name', () => {
return new HttpResponse('John')
}),
]
You can also use
HttpResponse.text()
shorthand static method.
JSON responses
A much more common response body type is JSON. Provide the JSON you wish to respond with as an argument to the HttpResponse.json()
static method to create a mocked JSON response:
import { http, HttpResponse } from 'msw'
export const handlers = [
http.post('/auth', () => {
// Note that you DON'T have to stringify the JSON!
return HttpResponse.json({
user: {
id: 'abc-123',
name: 'John Maverick',
},
})
}),
]
We recommend using the
HttpResponse.json()
shorthand static method to automatically keep theContent-Type
andContent-Length
response headers in-sync with the response JSON body you’re using.
Stream responses
You can respond with a ReadableStream
to stream any data back to the client.
Streaming
Respond with a `ReadableStream`.
Other responses
There are many other response body types you can describe with MSW, like XML, Blob
, ArrayBuffer
, or FormData
. Please refer to the HttpResponse
API to learn more about using other response body types.
HttpResponse
API reference for the `HttpResponse` class.
Mocking error responses
Construct and return a valid error response from a response resolver to emulate an error response.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/user', () => {
// Respond with "401 Unauthorized" to "GET /user" requests.
return new HttpResponse(null, { status: 401 })
}),
]
Mocking network errors
Use the Response.error()
or HttpResponse.error()
static method to raise a network error. Unlike an error response, a network error will halt the request execution and will mark that request as failed. In practice, you may experience network errors when constructing an invalid request or requesting hostnames that cannot be resolved.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.post('/checkout/cart', () => {
return HttpResponse.error()
}),
]
Throwing responses
You can throw a Response
instance at any point in the response resolver. When that happens, the request handling short-circuits, and the thrown response is returned as the mocked response.
import { http, HttpResponse } from 'msw'
http.post('/login', ({ request }) => {
if (!request.headers.has('cookie')) {
throw new HttpResponse(null, { status: 400 })
}
})
This is particularly handy to implement a middleware pattern when handling requests.
async function isAuthenticated(request) {
if (!request.headers.has('cookie')) {
throw new HttpResponse(null, { status: 400 })
}
}
http.post('/login', async ({ request }) => {
await isAuthenticated(request)
return new HttpResponse(null, {
status: 302,
headers: {
Location: '/dashboard',
},
})
})
Note that any non-response exceptions will be translated to
500 Internal Server Error
responses, similar to an unhandled rejection happening on server runtime.