Lesson Description

The "Mock Service Worker" Lesson is part of the full, Enterprise UI Development: Microfrontends, Testing, & Code Quality course featured in this preview video. Here's what you'd learn in this lesson:

Steve discusses how testing in environments where code is split across multiple teams or services can be challenging. To address this, he recommends using the Mock Service Worker library, which intercepts network requests in the browser to simulate API responses without mocking the app's internal code. This approach allows frontend development and testing to proceed independently of backend availability.

Preview

Transcript from the "Mock Service Worker" Lesson

[00:00:00]
>> Steve Kinney: I did a long course on testing not too long ago, where we go all the way deep in the weeds of mocking and testing and all that fun stuff, and we're going to do one on Playwright in depth. So I, again, like trying to cover the breadth in a lot of cases of what this means in terms of monorepos and micro frontends and keeping us focused. I'm going to focus on one particular aspect here, we can go in deeper later, which is to harken back to what we were talking about earlier, which is the nice thing about the monolith: if all of your code is in one place, you can test all of your code in one place, right?

[00:00:40]
What do you do when you don't own all the code, right, and as frontend engineers, a common place for this is like, do you want your tests to fail because the backend tests are failing? Right, depending on if it is a canary build, yes, but if it is like your job was to change some CSS and now CI isn't passing because, you know, one of the things I've experienced in my life is for teams that are building on AWS a lot of times and they don't have a local environment, staging a lot of times for—I've worked in a lot of companies where that is like staging is development, right?

[00:01:30]
It's like, oh yeah, I'm working on that API right now, it's currently broken, and I can't have my build. I can't have all frontend code stop shipping because one backend API is broken because someone's trying out an idea, right? That is, you can argue, shouldn't they fix that? Yeah, politics are hard. And one of the strategies that are really good for this is there's a library called Mock Service Worker that secretly we've been using through this entire workshop.

[00:02:02]
Right, all those API calls, I don't have an API. Mock Service Worker is a pretty cool library because effectively, if you're not familiar with what a service worker is, a service worker is a web worker that lives in your browser, and it actually can keep running even when you're not on the web page, right, and it can do stuff like background sync and cache your CSS offline so that you can have an offline mode to your app.

[00:02:36]
But one of the things, and really, as, you know, the way that the caching works is like, let's say it's going to look for style.css, right, and let's say you're offline. Like, one of the things you can do as a service worker is you can intercept network requests and redirect them, right, in the browser as you go. So like, if you were trying to build an offline app, right, what you could do is, oh, they went to go, you know, like tried to fetch style.css, cool.

[00:03:10]
Network's offline, use the one from cache so that the app still loads, right? If they're online, go try to get the fresh one. If they're offline, fall back. Oh, they submitted the tweet, right? Put it in IndexedDB, wait until we reconnect, then go send it, right? And so Mock Service Worker is interesting for both development as well as testing when you don't control the entire surface area, because what it allows you to do is not necessarily like mock the actual fetch, window.fetch, which is compelling in a lot of cases, right, but it allows you to do is have your app running, true as it ever was, as it ever did, and so you're not like, because the more you mock out your code, the more like you could have code that doesn't work in your test pass because you broke everything, right?

[00:04:05]
So with Mock Service Worker, it basically is intercepting all these network requests and can then just like be effectively like almost running an Express server, except it's all happening in the browser. But this is kind of what it looks like in this case, where if you've ever written Express before, this should look somewhat familiar, right? And it's like we have http.get. Whatever, we can do the full URL because like, you know, maybe your API is not running at the same domain, right, and basically what is happening is that this will get installed and like run as a service worker, like behind your app.

[00:04:42]
Your app doesn't even know it's there, so your app is behaving normally. So you're not like mocking out everything, you're just mocking out the network requests. Because again, this could be super useful for like even, you know, pulling down like the other module federation stuff and then like in your app, you're working against like, what, you know, like some mocks of whatever was, you know, like last pulled down from production, right?

[00:05:08]
And like when they go to request that other module federated module, we can respond to that. It's also really useful, like if you want to speed up your tests or something like that or not have to worry about like spinning up the API and the database and all that kind of stuff, you can basically like have these like kind of like mock versions set up. So yeah, you can, if you have a source of truth like the OpenAPI spec, like clearly like you could like, there are plenty of libraries that will just generate the REST.

[00:05:41]
If you don't have that, you can go ahead and you can like record it. Or like the other useful part about this is, let's say you're working with the backend team on a new feature. What we'd never want to end up in this situation is like, oh well we gotta wait for the backend to build the API and then we'll start on the frontend. Ideally, what you want to have is, you know, that contract, even if it is swaggered out with no implementation on the other end, right, then you can theoretically, even in development, set this up as if it was a real API and then there's always a cost integration, right, when it, like, you'll do your best, don't make a boo boo, you'll have made a boo boo, like, fine, but you can also like, cause again, you're just taking JSON objects and in this case returning them, and like your app, again, has no custom code in it.

[00:06:39]
It's just sending HTTP like it thinks it can, and then this is like returning like kind of mocked out responses, right? So it gives you a lot of power for development, gives you a lot of power for tests because now you don't have to like spin up an entire Docker environment with a mock database, right, or like a separate Express server. And, you know, I think it provides a lot of power in that sense as well.

[00:07:06]
You know, and you've got to figure out like interesting stuff like, you know, if a URL is not completely idempotent, like, you know, you've got to do some logic of like, what happens about the fourth time I hit it. At what point are you just actually doing the backend work? It becomes a little tricky, but for like, you know, if you had like a Storybook and you're trying to test different states, you want to test the unhappy path.

[00:07:29]
You're like, I want to have a test, you can have a general one that you kind of install and run. We'll actually look at it in the example apps in a second. But I think down here, you know, obviously when you're doing your test, you can like start one fresh in every test framework, you know, or every, like before every test, I want to set up the server as if nothing happened to it, you know, over and over and over again.

[00:07:59]
And then like if you need to override one of them, there is, you can say like, for like once, I want to like have it return a 500, right, so now you can actually like simulate the unhappy paths super easily as well, which is like blow up no matter what, so I can test the failure state. What happens if I have module federation and I want to test what happens if the dashboard doesn't load at all, right?

[00:08:24]
You can do that for like one test and like have, you know, either Playwright or your unit tests, right, or stuff along those lines run it as well. And there's a way to like, it's using Service Worker if you run it in the browser, and then like there's, you know, a way to do it with like Node as well, which is really a lot of times like where unit tests are running, right? So you'd be like, okay, do we handle that failure well, you can do it in your component test at that point, which are still usually running in Node cause they're effectively unit tests, you can make sure that like the component does the thing, right?

[00:08:54]
But it's also great for like simulating the boundaries that you don't control, right? Because yeah, maybe they, maybe they're working on something or maybe the other team like, you know, their thing went down, they shouldn't like stop everything on your team in this case. And so like, you get a lot of like flexibility and power and like, again, you can use it in development, you can use it to secure your tests, you can use it to create intentional unhappy states and all those things you fire in a Storybook and then have like known cases where it's like, okay, what is this form when the backend totally just like went down or when it like rejected it, and so on and so forth and put it in all of those states and becomes like incredibly powerful without mocking out your own code.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now