- 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
HttpResponseclass encapsulates useful shorthand methods for declaring responses, likeHttpResponse.json(),HttpResponse.xml(),HttpResponse.formData(), etc. - Unlike the native
Responseclass, theHttpResponseclass enables support for mocking response cookies by setting theSet-Cookieheader 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!')
}),
]
HttpResponseis 100% compatible with the nativeResponseclass. Under the hood,HttpResponsereturns a plain Fetch APIResponseinstance.
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-TypeandContent-Lengthresponse 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 Errorresponses, similar to an unhandled rejection happening on server runtime.