Mocking responses

Declaring and using mocked responses.

Responding to an intercepted request with a mocked response is one of the most common use cases for MSW. Note that it isn’t the only way to handle a request. This page will give you an overview of how to create mocked responses and use them in your request handlers.

Fetch API limitations

When working with MSW, you will be using Fetch API Response instances to describe mocked responses. Relying on a web standard allows for a familiar and flexible mocking experience, reusing of the existing network utilities, and transferable knowledge.

While you always write your mocks from the server’s perspective, the Fetch API isn’t designed to declare server responses. The API contains several restrictions that make sense on the client but less so in your mocks:

  • Some response headers, like Set-Cookie, are forbidden;
  • Setting status codes outside of the 2xx-5xx range are forbidden;

None of these restrictions apply when mocking responses with MSW. You can mock cookies, set otherwise non-configurable status codes, like 101 Switching Protocols, and declare mocked responses as you would server responses. That is achieved by using the HttpResponse superset class provided by the library. Please prefer using it when declaring mocked responses.

Responding to requests

Return a mocked response

You can respond to an intercepted request with a mocked response by constructing the Fetch API Response instance you want and returning it from the response resolver.

import { http, HttpResponse } from 'msw'
 
export const handlers = [
  http.get<never, never, string>('/resource', () => {
    return HttpResponse.text('hello world')
  }),
]

You can return a plain Fetch API Response instance, too. It’s recommended to use the HttpResponse class instead, which is a drop-in replacement for Response but provides improved developer experience and unlocks otherwise unavailable features, like mocking the set-cookie header.

Throw a mocked response

If you throw a Response instance at any point in the response resolver, that response will be used as the mocked response for the request. This is particularly handy for short-circuiting the resolver flow anywhere during the request handling.

function withAuthorization(request: Request) {
  if (!request.headers.get('authorization')) {
    throw HttpResponse.text('Unauthorized', { status: 401 })
  }
}
 
http.get<never, never, { id: string }>('/resource', ({ request }) => {
  withAuthorization(request)
  return HttpResponse.json({ id: 'abc-123' })
})

In this example, the GET /resource request will get a “401 Unauthorized” response if it doesn’t contain the Authorization header. Otherwise, it will proceed with the mocked JSON response.

Response declaration

It is highly recommended you get yourself familiar with Fetch API Response class. Mocking various response scenarios will come down to declaring them using that standard class. Below, you can find a few common examples. Make sure to explore the section to your left for more advanced use cases.

Status code

http.get('/resource', () => {
  return new HttpResponse(null, { status: 404 })
})

Response headers

http.get('/resource', () => {
  return HttpResponse.json(
    { id: 'abc-123' },
    {
      headers: {
        'content-type': 'application/hal+json',
      },
    },
  )
})

Response body

You can use all the supported response body types, like strings, Blob, ArrayBuffer, FormData, URLSearchParams, and ReadableStream as the body of your mocked response.

http.get('/resource', () => {
  return HttpResponse.text('hello world')
})

Learn more about the static shorthand methods like .text(), .json(), and others in the HttpResponse API reference.

Next steps

Please explore the “Mocking HTTP” section for more recipes and advanced mocking scenarios. Here are a few noteworthy ones: