Mock Service Worker is awesome
Tags: javascript, react, testing, architecture
Published: 2022-08-25 05:46:00

One of the biggest hurdles for any kind of UX development is the data. We've all been there: we have design layed out, some features in the backlog and we are eager to start developing our new app. But we are depending on the data from the API. 

The usual way to overcome this and not be completely blocked by this situation is to use some static mock data and create our components in some component development environment, e.g Storybook. Having static mock data would allow us to develop some presentational components, but the real meat and potato of our app would need to be developed only after we get the actual data.

The other way is to have the API return some mock data, which we will use in our app, and only when the back-end team provides us with some mock data they can start working on actual features. Again, this is sub-optimal: it slows down back-end team and it puts a lot more pressure on them to get the mock data first and postpone real feature development.

The workflow which would make both teams a lot happier could be to have an agreement on the API spec, which both teams can use as a guide when designing the data model, and to develop its set of features in the order that makes more sense for both sides.

From the front-end perspective, a tool that allows this kind of workflow is [`Mock Service Worker`](https://mswjs.io/), or shorter `msw` and that is what we are going to talk about in this post.

### Mock Service Worker (`msw`)
Simply put, `msw` is a tool for API mocking. It mocks API calls by installing a service worker for you which intercepts network calls to the API and calls your registered handler functions instead. You, as a developer, need to worry only about writing handler functions for endpoints your app is reaching to.

It supports both REST and GraphQL APIs, it can delay the response of mocked API endpoints so the endpoint feels more real-life, it has it's own in-memory database with [`@msw/data`](https://github.com/mswjs/data) package for more complex querying (e.g, searching, sorting), it can also run mocks in NodeJS environment instead of Service Worker (really useful for testing). Next, let's take a look at which problems `msw` can solve and how.

### Benefits of using `msw`

#### Testing

Imagine a React component that fetches some data from an API and than it renders that data on to the page. What are our testing options? We could mock the function or a library that is doing the fetching, we could mock the underlying `fetch` call or we could intercept the network call in some way (e.g, with `msw`). 

The first approach would give us a confidence that our component is calling a function that should return us data, the second approach is giving us confidence that our component **integrates** properly with the fetching library (`swr`, `react-query`, plain `fetch` or `axios`) and the last approach is giving us confidence that we are **making** the right HTTP call. 

The beauty of intercepting the network call with `msw` in our tests is that we are gaining a lot more coverage and thus confidence in our tests, that test reflects real-life way more and we are not coupling our tests with the fetching library. Imagine we needed to change a library we use for making network calls, e.g from `swr` to `react-query`. Since we are not actually mocking a fetching library in our tests we don't need to change them at all. In any other scenarios listed above, we would need to refactor our tests as well. Double win!

#### Independent FE development

My first experience with `msw` was on a project where I was the only FE developer and I had a BE team of two. We had a really short deadline (1 month) to deliver an app. Both FE and BE were starting from scratch, and the back-end needed to do some work on infrastructure, getting the data sources and writing migration scripts for that data, etc. The client wanted a demo every week to see how the app is coming along. I proposed `msw` as a way to unblock my development, we would just need to agree on the data models. As we had clear requirements about how the data should look, that part wasn't that difficult. 

Using `msw`, we were able to conduct the demo every week with mocked endpoints that looked realistic. Endpoints had a delay of 500ms to return data, the data between pages was connected (clicking on a table row loads relevant details page), searching returns relevant data, etc.

Once the backend team had some endpoints done, I just removed `msw` handlers for those endpoints without making any changes to the underlying code. The side-effect is that I had tests that were using the same handlers for realistic tests. `msw` was a crucial organizational tool on that project that increased team's velocity and made the biggest impact on the project's success.

#### Debugging

Every once in a while there is a bug in our code that is happening only when a certain response is returned from an API. If you don't have control over the API (some other team is responsible for it, it's a vendor API) than it means that you would need to somehow change the HTTP response in troubling response. Traditional method in these kind of situations is using an OS proxy app like `Charles Proxy` or `Wireshark`, but they can be really difficult to setup and to run properly (you have to deal with certificates to see HTTPS calls, etc.). 

Alternative is to spin up `msw` that mocks the endpoint that you need and to just return the data to stress the app with. It's way, way faster and simpler and you can also use that handler to write a test for that scenario (I'm repeating myself, I know).

### Conclusion

In this post I've shared my experience using `msw` library in my own projects and what could be potential benefits for you and your projects. I hope you will give it a try. Let me what is your experience using `msw` in the comments.