LOGOMock Service Worker
  1. Recipes
  2. Request assertions

Request assertions

When testing, it may be tempting to write assertions against a dispatched request. Examples of such assertions can include:

  • Check that the tested code has dispatched a request;
  • Check that a request was issued with the correct URL/parameters/body/etc;
  • Check that a specific request handler was called.

Adding such assertions, however, is implementation details testing and is highly discouraged. Asserting requests in such way is testing how your application is written, instead of what it does.

Mock Service Worker gives you a guarantee over network communication.

Instead of asserting that a request was made, or had the correct data, test how your application reacted to that request.

Your application fetches data for a reason, so prefer testing that reason as the outcome of the request. If a request's method, headers, or body are invalid, your application is likely to get an invalid response back. Below we are going to take a look at some recommended strategies to request testing.

Special cases

There are, however, some special cases where asserting on network requests is the only option. These include, for example, polling, where no other side effect can be asserted upon.

For such cases, Mock Service Worker allows tracking of network requests through the Life-cycle events API.

Include failure scenarios

Validity of the response often, if not always, depends on the validity of the request. Include any necessary validation and utilize conditional mocking to reflect a request's integrity in your response resolvers.

For example, your application is making a GET /search?type=ABC request where the type parameter represents a search type, and should be either product or user. That query parameter value validation is a business logic, so reflect it in your response resolver to ensure your mocks respect that logic.

1import { rest } from 'msw'
3rest.get('/search', (req, res, ctx) => {
4 const searchType = req.url.searchParams.get('type')
6 // Successful response in case the "type" query parameter
7 // passes the value validation.
8 if (['product', 'user'].includes(searchType)) {
9 return res(
10 ctx.json({
11 results: [1, 2, 3],
12 }),
13 )
14 }
16 // A failure scenario that ensures our mocks don't tolerate
17 // unknown "type" query parameter values.
18 return res(
19 ctx.status(400),
20 ctx.json({ message: `Unknown search type: ${searchType}` }),
21 )

By accounting on the failure scenario, you can rely on your application's output in your tests being a reflection of the request's validity.

Remember that mocks execute next to the rest of your application. Import validation utilities, constants, and other useful data to reduce the amount of repetition in your mocking setup and keep it aligned with your application's logic.

Including partial representation of the business logic is also beneficial, as it helps mocks to represent the state of an API in a point of time, making mocks useful when reasoning about API's behavior.

Treat unhandled requests

To ensure that your application doesn't perform any requests rather than the ones defined in your handlers, consider using onUnhandledRequest option. This option allows to warn or throw an error whenever an unknown request is dispatched.