Testing Vue 3 Applications with Mock Service Worker

Rate this content
Bookmark

In this talk, we will discuss some best practices for testing Vue 3 applications. We will explore how the Mock Service Worker and the Vue Testing Library can aid us in testing Vue 3 applications closer to a real-live user situation. Attendees will leave with a solid understanding of how to effectively test their Vue 3 applications to ensure reliability and maintainability.

24 min
15 May, 2023

Comments

Sign in or register to post your comment.

AI Generated Video Summary

This Talk discusses testing V3 applications with Mock Service Worker, which is a library that allows simulating server responses in tests. It covers setting up Mock Service Worker by creating mock API responses and connecting it with the application. The Talk also explains how to write unit tests for asynchronous components using Vue's suspense component. It demonstrates how to test components that interact with APIs and handle error responses. Additionally, it mentions the testing library for components without API calls and emphasizes the importance of testing component interactions and API integration.

1. Testing V3 Applications with Mock Service Worker

Short description:

Hi there. Today I'll talk about testing V3 applications with mux-serviceworker. We'll explore how to use V3 with mux-serviceworker to improve code quality and testing. Testing V3 applications is crucial for catching bugs early and increasing confidence in code. Mock Service Worker is a library that allows you to simulate server responses in tests, making it useful for large applications with API interactions. It's also great for running unit tests in a continuous integration environment. Let's look at an example using mock service worker in a Vue 3 app to mock API responses and test components that interact with the API.

Hi there. I want to tell you today about testing V3 applications with mux-serviceworker. I'm Lizzie. I'm a frontend architect at Storyblock. You can find me on Twitter, but most importantly, you can find all the examples that I made for this talk in this GitHub repository.

And let's dive right into it. So this talk is based a little bit on Harry Potter. And we will figure out how we can use V3 together with mux-serviceworker to improve our code quality and to test in a better and more integrated way.

So why is it important to test V3 applications? It's really crucial to perfecting your code, to making sure it's doing what it should. It can really help you to catch bugs before they go into production, because if you catch a bug in production, it's a lot more expensive. So the earlier you catch the bugs, the better. And it can really help to increase the confidence in your code and the code you're writing and also the code you're changing.

So what is Mock Service Worker? Mock Service Worker is a really nice library that you can install into your application and it allows you to simulate server responses in your tests. So you can create a mock API and you can test how actually your application is handling the responses of the server and also handle edge cases of server responses, which might return errors. Why would you use that? It's really important in large applications that have a lot of API interactions. So many large applications like Storyblock, they have a lot of API interaction and you want to make sure that all these different components, they're actually working as they should work with these different responses you can get from the API. It's also really nice if you run your unit tests in a continuous integration environment. For example, you run your unit tests in GitHub Actions, and inside of that continuous integration environment, you cannot call the API. So you need to mock the API and run the unit tests with actual mocked responses. And that's where using mock service worker is really nice.

All right, let's look at the example I built and how we can actually set it up. To start using mock service worker, you can start using it in a view 3 app. You need some kind of testing environment. So in this example, we'll be using vitest, but it works with Chest just the same. And you need mock service worker, which is the library that is in the core of this talk. So the example I built, it's showing my magical beasts. We have a headline. We have some cards with the USB stick, and we can click on those cards and see some more details of the magical beast. And all the content here, it's loaded from an API. So I have a story block space where I set up some content.

2. Setting up Mock Service Worker

Short description:

I have a page that has the headline and the different magical beast. I fetch the actual content from the Storyblocks API to show the details of the magical beast. To mock the API, I create a mock directory with JSON files that replicate the API responses. Then, I set up the mock service worker and handlers. This involves creating a setup file and connecting mock service worker with YDist.

I have a page that has the headline and the different magical beast. And then I can also see what's actually returned there. So through the API from story block, I get the actual content that I can then use to show my content, the same for the more specific pages. So I have a magical beast and then I have some content here that shows all the details of that magical beast.

All right. So let's start. The first thing for making a mock service worker setup is that you actually need some kind of API, you need some kind of asynchronous way of interaction. So in my example, I have a component that fetches, just does a simple fetch to Storyblocks API and that has all the responses. And then from that response, I build the actual page that we see. And the important part here is that now we need to mock the API. So our first step is to actually create a mock directory. In the root of our project, it could also be somewhere else, but I will do it in the root. And then we set up the mock service worker.

So what do I mean with a mock directory? If we look into the example, we have a folder there that's called mocks. And then we have two JSON files. So we have the beast JSON, that's the start page. And then we have the niffler JSON, that's a mock of the actual, more specific page. How can you get those JSONs? The simplest thing is to have your application, and then check in the network what is actually being returned by the API. So if we reload that, my mock here is basically this request and this response we have here. So the story, I could just copy that and paste that here into my beast JSON file. So this one is just a copy of what I had on that page. So that's really the first part, to have some mocks that can be used by the mock service worker, but also by other unit tests that might not need the mock service worker.

Then the next step is to actually set up mock service worker and to set up some handlers. So for setting up the mock service worker, we need to actually create a setup file. So in the white disk config, we can configure some setup files. So you will provide the path to the file that is setting up our testing environment. Then here in test setup, I have this index.js file that has my global testing setup. So that's the setup that is used in all the tests that I'm writing. I also have some other stuff here, but the important part is here, the mock service worker setup file, where I connect mock service worker with YDist. So before all, after all, and after each test, we're starting the server, we're closing the server, and then we're resetting the handles after each test.

3. Mock Service Worker for Efficient Testing

Short description:

The core part of setting up mock service worker is importing it and providing handlers. Handlers connect the API with specific methods, such as GET requests, and return a JSON mock response. This setup allows us to write unit tests for specific pages or endpoints. With the server and handlers in place, we can begin writing our first unit test.

And then the actual server that we're creating. So that's the core part. We're importing from mock service worker and we're providing it with some handlers. The handlers are the core part of setting up mock service worker. And what the handlers do is that they connect a REST API, or you can also do a GraphQL API with a specific method. So you say, for example, I have a GET, a REST GET request that cause the endpoint API store block, whatever. And when that happens, I want to return the status 200 and then please return a JSON of this mock that we just created. So we're returning a mock response and we can use that then in our unit tests. We do the same thing for the more specific page of that magical beast. So here we're really connecting JSON example response with the endpoint and this connection will help us write then the unit tests. So you do not need much more than that, setting up the server and setting up the handlers and then we can already start flying and write our first unit test.

4. Writing Unit Tests for Asynchronous Components

Short description:

To write a unit test for this page, we need to consider its components and asynchronous nature. Vue's suspense component helps with handling asynchronous behavior. We import the asynchronous component and wrap it in a suspense component for testing. To wait for the fetch to happen, we create a spy on window fetch. We then mount the component using the mount function from the view test utils. After waiting for the fetch to be called, we use the flush promises helper to ensure promises are resolved. Finally, we write the tests and access the h1 element.

So the next step here is really to write a unit test for this page. When writing a unit test, you have to think, well what does it do? It shows a headline and it has three cards that have some content. So the view setup of it is pretty simple. But the complexity here comes a little bit with the assynchronity. So we're testing an asynchronous component. And in Vue, we can do that by wrapping it in a suspense component. So this is a fairly new component in Vue 3 that can help us deal with asynchronous behavior.

All right. Let's look further into it. So we have that file in our Vue that's asynchronous, like here, for example. We have some html. And the important part is that we have a fetch, and we have to wait for the response of the fetch. If we look into that component, we can see here we're importing the component. And then we're wrapping it in an asynchronous component just so we can test it, because it is an asynchronous component. And then we can write the actual test.

So in the actual test, what we do is, since it's asynchronous, we wait for the fetch to happen. How you can do that together with mock service worker is by creating a spy. So we're creating a spy on window fetch, and we will call that getSpy. You can do that also with Axios. So you could create a spy that works with Axios that does the same kind of spying. It really depends on which way you're using to talk to your API and get your responses. The next step is to actually mount the component. So we get this mount function from the view test utils. And then comes the asynchronous part. We wait for this get, this fetch function to have been called one time. And then we use a helper that's called flush promises. It's a helper for the view test utils to help us make sure the promises are solved. And then finally, we write the tests. So we get the wrapper for the test. We get the h1 element.

5. Connected Unit Test with Mock Service Worker

Short description:

We get the text of the h1 element and ensure it matches 'my magical beast'. We verify that there are exactly three elements with the VA card class, simulating three cards in the unit test. The global test setup automatically fetches the JSON response when the endpoint is called, allowing the component to function as it would in a real environment. The test cases include checking if the heading is shown, if there are three cards, and if the second card displays the expected content. MockServiceWorker can simulate error responses or longer delays by creating new handlers. Error handlers return a 403 status and an error message, mimicking a scenario where a user calls an unauthorized endpoint.

We get the text of that. And we said, well, the text of my h1 element should be my magical beast. And then we find all the elements that have the VA card class. And we say, well, there should be three elements that have the VA card class. So that are three classes. So it makes sure there's exactly three cards in this unit test. And that's basically already our connected unit test with mock service worker. And it's pretty cool because we don't have to write this really crazy extensive mocks. But with this global test setup, when our endpoint is called here with the window fetch, it will automatically fetch this JSON we have here. And the component works as it would work also in the real environment. And then when we write the test, we can make sure that the setup of that component is actually like it should be.

So let's look at the test we wrote here. One second, I just run the file. So here, we have this before each. So it mounts the component before each test so that we do not have to rewrite this in every test. And then we have the different test cases. The first one says, well, the heading should be shown. There should be three cards. Then we have also another test case where we say, well, the second card should always show an if-not element that tests actually for that content we have there to make sure the content is shown in the way that we want to show it. All right, and yeah, that's already connected.

And now comes the interesting part because MockServiceWorker, it can not only simulate these positive responses, but it can also simulate error responses or longer delays. And we can do that by just creating new handlers that actually return something else. So inside of our mocks, I created a file that's called error handlers. And error handlers looks really similar to the handlers that we had before. Again, it's using the rest method from MockServiceWorker. We make a GET request to the same endpoint, but instead of returning a context status 200, we're now returning a context status 403. And then the endpoint will return an error message with not allowed. And that basically would mock a behavior where you'll say a user is calling an endpoint that is not allowed to call that input. For example, a user is calling an admin endpoint, but the user might not be an admin. To show you what I mean in the browser, I can show you that here.

6. Testing Error Responses and Edge Cases

Short description:

So here, we can block a URL and see the error. I adapted my component to handle error responses. To test this behavior, import the server and error handlers, create a test suit for failing requests, and check if the HTML contains the error response. Testing with failing API responses ensures coverage for potential failures. Mock Service Worker makes testing easier and more powerful, allowing for testing edge cases like delayed APIs or custom error messages. MOCs can be used in unit tests without the MOC service worker.

So here, if we look at the network again, let's reload that. And then we can block this. We can block this URL. And now if we reload, it cannot load, because this URL is blocked. The browser is not allowing us to. And then we see this error here.

So I adapted my component to be actually able to handle this kind of error response. So inside of my home view, it's gotten a bit more complicated where I checked the response. I checked the response status. And if it's not at 200, I'm throwing an error. And this error is then shown inside of my page. And now I can write the test for it.

So to test this behavior with errors, what we need to do is we need to import our server that we're using that is active. And we need to import our error handlers that have the actual error handling responses. And then I can write a new test suit for the failing requests. And I can say, please use the server with the error handlers instead of the other regular handlers to see how my component behaves with a failing API response. Then I wait for that to be loaded and finished. And then I write the test case where I say, my HTML should contain this error response that is returned from the error handler. So the text that the API's returning should be shown in my HTML. And if we look at these error handlers, this is the message that is returned here. And then you're testing the same component, the same asynchronous component, with actual failing API responses, which makes it even more clear and make sure that we're also covering cases where the API might be failing. So this is really cool. And this is something that's rather hard to do when you have to write it yourself and you don't have the mock service worker. So you have to do a lot more without the mock service worker to get this kind of testing behavior. So it's really, really powerful. You can also test other edge cases. So APIs have unusual behavior, and you can test test cases, for example, where the API is delayed for two seconds. Or you can test cases where you have some custom error message or some custom response because some custom case happened, like a user calling an endpoint that he should not be calling. Of course MOC service worker is not the only way to test. You can use these MOCs that we created also in unit tests that are not using the MOC service worker.

7. Testing Components without API Calls

Short description:

For components that don't call an API, the testing library is recommended. It's a wrapper around the view test utilities, providing better accessibility testing. It ensures the right elements are on the screen and tests user interaction. Let's look at an example of testing a component with a click behavior. The component is a simple view component that receives a prop called Block. The test imports necessary functions and components, sets up the mock data, renders the component, and executes test cases.

So for components that are not maybe calling an API, they're just regular components that are not asynchronous. For the smaller units, I can really recommend using the testing library. It's a really nice wrapper around the view test utilities that can test even better for accessibility. It can test if the right elements are on the screen. It can test for user interaction. So it's really good in making these click behaviors or input field behaviors to make sure your components are behaving like they should for user interaction.

And I will show you a quick case of our example. So let's disable the blocking here. So if we go to our element here, it's a simple component that receives a prop. And we now want to test those component and maybe test this click behavior that we have here on the buttons, or that we have a button. I will show you the actual test.

So this is our component. So it is a simple view component with a lot of HTML. And it basically only receives a prop called Block. That's very common in applications that use Storyblock. And then everything that's shown here is based on top of this block prop it's receiving. And then here we can go into the test for this component. And you see here we are importing the render screen and fire event functions from the testing library view. So that's kind of the core functions you would need when you test with this library. I'm also importing the config because I wanted it to receive some of the global configuration I already had configured. And then I import the component.

Here I don't need this async wrapper because it's not an asynchronous component that's waiting for some API response. It's just a simple component. And I'm also importing this mock that I created in the early beginning where I just copied the response I got from the server. I then create the actual prop that is passed to the component. So what's passed to the component is inside of that whole mock. So I get the specific part of the mock that I need to pass it to the component. Then I render the actual component. I pass the content, the mock, to that component. And then I can have the different test cases.

8. Testing Component Interactions and API Integration

Short description:

In addition to testing specific attributes, this library allows for testing interactions and ensuring component behavior. By using the same mocks as the mock service worker, we can define the interaction point between the API and the application in one place. This ensures that components are working with the API's data and helps prevent application breakages. For more resources, check out the mockserviceworker documentation, the testing library for testing components and interactions, and Vue.js guides on asynchronous behavior and suspense. You can also use Storyblock to create your APIs. Try it out in your Vue 3 application!

So here I'm testing that the name of the magical piece, the description, and the image are there. I can also test. And that's what's cool about this library is that I can test by alt text. I can test by placeholder. And this can be really useful for making your application more accessible because we do not only tests for specific tests, but for actual HTML attributes.

And then finally, I can also test some interaction. So here I'm saying I want to have exactly one button with the text. And then when I click on that button, I want to be sure that this component emitted the specific event. So this basically tests this behavior that this component is emitting an event when we click on it. And now if someone would go into this component and remove this button, then our unit test would fail. And we would see, well, something went wrong because it's not fulfilling this button behavior anymore. The same thing would happen if this person would change this button to a div. The unit test would be failing because we've been really specific in saying, well, there should be a button with that name that should emit exactly this event. And this helps us make sure that our application is not breaking.

And as you see here, it's not using a mock service worker. It's not asynchronous, but it's using the same mocks that we're also using together with the mock service worker. And that's really helpful because we have one place where we define the interaction point between the API and the application. So if all the tests are using the same kind of mocks and if my API is changing, I also have to change the mocks. But I can make sure that my components and my components when I'm testing them are actually working with all the things that are coming from my API.

All right. That's basically it. I have some more resources. So mockserviceworker has a really nice documentation. The testing library is really great for testing simple components and testing interactions. Vue.js has also a lot of great guides on how to work with asynchronous behavior, how to work with suspense, and also how to test asynchronous behavior because it's not actually that easy. And yeah, you can also use a story block to create your APIs. And yeah, that was really fun to actually do and learn and set up. And I hope you use this repository to try it out in your own Vue 3 application. Thank you very much for listening.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Vue.js London Live 2021Vue.js London Live 2021
20 min
One Year Into Vue 3
Vue 3 may still sound new to many users, but it's actually been released for over a year already. How did Vue 3 evolve during this period? Why did it take so long for the ecosystem to catch up? What did we learn from this process? What's coming next? We will discuss these questions in this talk!


TestJS Summit 2021TestJS Summit 2021
33 min
Network Requests with Cypress
Whether you're testing your UI or API, Cypress gives you all the tools needed to work with and manage network requests. This intermediate-level task demonstrates how to use the cy.request and cy.intercept commands to execute, spy on, and stub network requests while testing your application in the browser. Learn how the commands work as well as use cases for each, including best practices for testing and mocking your network requests.
TestJS Summit 2021TestJS Summit 2021
38 min
Testing Pyramid Makes Little Sense, What We Can Use Instead
Featured Video
The testing pyramid - the canonical shape of tests that defined what types of tests we need to write to make sure the app works - is ... obsolete. In this presentation, Roman Sandler and Gleb Bahmutov argue what the testing shape works better for today's web applications.


TestJS Summit 2021TestJS Summit 2021
31 min
Test Effective Development
Developers want to sleep tight knowing they didn't break production. Companies want to be efficient in order to meet their customer needs faster and to gain competitive advantage sooner. We ALL want to be cost effective... or shall I say... TEST EFFECTIVE!
But how do we do that?
Are the "unit" and "integration" terminology serves us right?
Or is it time for a change? When should we use either strategy to maximize our "test effectiveness"?
In this talk I'll show you a brand new way to think about cost effective testing with new strategies and new testing terms!
It’s time to go DEEPER!


TestJS Summit 2022TestJS Summit 2022
27 min
Full-Circle Testing With Cypress
Cypress has taken the world by storm by brining an easy to use tool for end to end testing. It’s capabilities have proven to be be useful for creating stable tests for frontend applications. But end to end testing is just a small part of testing efforts. What about your API? What about your components? Well, in my talk I would like to show you how we can start with end-to-end tests, go deeper with component testing and then move up to testing our API, circ

Workshops on related topic

React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents
- The different kinds of React application tests, and where component tests fit in
- A mental model for thinking about the inputs and outputs of the components you test
- Options for selecting DOM elements to verify and interact with them
- The value of mocks and why they shouldn’t be avoided
- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites
- Familiarity with building applications with React
- Basic experience writing automated tests with Jest or another unit testing framework
- You do not need any experience with React Testing Library
- Machine setup: Node LTS, Yarn
Vue.js London Live 2021Vue.js London Live 2021
169 min
Vue3: Modern Frontend App Development
Featured WorkshopFree
The Vue3 has been released in mid-2020. Besides many improvements and optimizations, the main feature of Vue3 brings is the Composition API – a new way to write and reuse reactive code. Let's learn more about how to use Composition API efficiently.
Besides core Vue3 features we'll explain examples of how to use popular libraries with Vue3.
Table of contents:
- Introduction to Vue3
- Composition API
- Core libraries
- Vue3 ecosystem
Prerequisites:
IDE of choice (Inellij or VSC) installed
Nodejs + NPM


TestJS Summit 2022TestJS Summit 2022
146 min
How to Start With Cypress
Featured WorkshopFree
The web has evolved. Finally, testing has also. Cypress is a modern testing tool that answers the testing needs of modern web applications. It has been gaining a lot of traction in the last couple of years, gaining worldwide popularity. If you have been waiting to learn Cypress, wait no more! Filip Hric will guide you through the first steps on how to start using Cypress and set up a project on your own. The good news is, learning Cypress is incredibly easy. You'll write your first test in no time, and then you'll discover how to write a full end-to-end test for a modern web application. You'll learn the core concepts like retry-ability. Discover how to work and interact with your application and learn how to combine API and UI tests. Throughout this whole workshop, we will write code and do practical exercises. You will leave with a hands-on experience that you can translate to your own project.
React Summit 2022React Summit 2022
117 min
Detox 101: How to write stable end-to-end tests for your React Native application
WorkshopFree
Compared to unit testing, end-to-end testing aims to interact with your application just like a real user. And as we all know it can be pretty challenging. Especially when we talk about Mobile applications.
Tests rely on many conditions and are considered to be slow and flaky. On the other hand - end-to-end tests can give the greatest confidence that your app is working. And if done right - can become an amazing tool for boosting developer velocity.
Detox is a gray-box end-to-end testing framework for mobile apps. Developed by Wix to solve the problem of slowness and flakiness and
used by React Native itself
as its E2E testing tool.
Join me on this workshop to learn how to make your mobile end-to-end tests with Detox rock.
Prerequisites
- iOS/Android: MacOS Catalina or newer
- Android only: Linux
-
Install before the workshop
TestJS Summit - January, 2021TestJS Summit - January, 2021
173 min
Testing Web Applications Using Cypress
WorkshopFree
This workshop will teach you the basics of writing useful end-to-end tests using Cypress Test Runner.
We will cover writing tests, covering every application feature, structuring tests, intercepting network requests, and setting up the backend data.
Anyone who knows JavaScript programming language and has NPM installed would be able to follow along.


JSNation 2022JSNation 2022
141 min
Going on an adventure with Nuxt 3, Motion UI and Azure
WorkshopFree
We love easily created and deployed web applications! So, let’s see what a very current tech stack like Nuxt 3, Motion UI and Azure Static Web Apps can do for us. It could very well be a golden trio in modern day web development. Or it could be a fire pit of bugs and errors. Either way it will be a learning adventure for us all. Nuxt 3 has been released just a few months ago, and we cannot wait any longer to explore its new features like its acceptance of Vue 3 and the Nitro Engine. We add a bit of pizzazz to our application with the Sass library Motion UI, because static design is out, and animations are in again.
Our driving power of the stack will be Azure. Azure static web apps are new, close to production and a nifty and quick way for developers to deploy their websites. So of course, we must try this out.
With some sprinkled Azure Functions on top, we will explore what web development in 2022 can do.