About this article
In this article I want to cover all you need to know before starting with your unit testing in Vue.js. This will include the reasoning behind testing in general and when to use them. I will also give an overview about what types of tests are available and how Vue.js CLI helps us in establishing our testing suite using Karma and Jasmine – two very powerful unit testing tools that make our life easier. In the end I will cover the basics on which parts of your components you want to test and how you should do that.
Why is testing so important?
As customers are more and more reliant on our services the important of quality assurance is rising dramatically. Even short outages or simple errors can result in a huge loss of money or customers. To prevent this, we need to ensure that our components work the way we expect them to.
Due to a high test-coverage we can be sure that our code is predictably doing what we expect it to do. Another thing we can test is its efficiency – an indicator of how well we can use our resources to handle incoming requests or operations. Having all these tests results in a higher maintainability and a better debugging experience.
What types of tests can we use?
There are different types of tests that can help us achieve our quality goal:
End-to-End tests are designed to simulate realistic user scenarios and include a broad range of the used stack. Their goal is to ensure that the workflows a user would go through are working as expected. While this makes them very appreciated by managers and customers, they also require a lot of effort due to their high complexity, their vulnerability to errors and high maintenance cost. Due to this most enterprises have less E2E-Tests as unit or integration tests.
Integration tests target the communication and interoperability of different services and components. These tests are especially important when dealing with external services and being required to work with their API.
Unit tests target the functionality of the smallest, testable components and services. They get tested in isolation, usually with mock-data to exclude external factors from the tests. Their goal is to ensure that the component or service is working 100% correctly and all features are implemented to their specification. Due to the high number of features that require testing these tests are usually the most common test type in any project. In this article I will mostly focus on this test type.
When should I test?
The best possible point in time to start writing tests is even before writing your first code. This approach is also known as Test Driven Development (TDD) and is defined as the following workflow:
A unit test is written to ensure that a future feature will behave according to the specification. Obviously, this test should fail the first time as there is no implementation of it, yet.
After we have a working test, the developer can start with working on the feature. Once he is done, he will execute the previously written test and check whether it passes or fails. On a failure he will go back to fixing his implementations until the test passes.
This process is repeated for every single feature and ensures that the component performs inside the acceptable criteria.
What about the test suite setup?
This is easy if you are using the Vue CLI 3, because all you need to do is to enable unit testing on the UI and it will integrate everything for you.
It is recommended to setup additional hooks on pre-commit and pre-build to automatically run your tests. This will alert the developer even before the failing code hits your remote server and stop it from infecting your project branches.
How to approach unit testing in Vue.js?
Even in unit testing there are still different types of approaches to what and how it should be tested:
White Box Testing
The structure, design and implementation are known to the tester and the aim is to ensure the internals of the component work as intended. This goes beyond testing the user interface to a level of checking single, internal functions with different inputs to verify their result.
Black Box Testing
During a black box test the internals of the component are completely ignored and the focus is on the component’s behaviour with the outside. Mostly this consists of a given input and checking if an expected result was returned or an expected event happened.
Grey Box Testing
In this scenario the inner workings of the component are partially known to the tester, e.g. the data structures or algorithms might be known for the design of the test cases, but the test will happen at a user or black-box level. In these test scenarios you will face the most challenges if you want to do it right.
Unit testing in Vue.js components and services
Mount vs Shallow mount
When testing Vue.js components with vue-test-utils you will have the choice whether to test them using the full
mount(myComponent) functions or to use ‘shallowMount(myComponent)’. The difference between those two mounting options is how they are going to handle your child components:
While the full mount function will load all your child components shallow mount won’t. This way you will have a cleaner, isolated test environment focused on the one component that you want to test; thus, this method is recommended.
What do I want to test?
When testing components, you should focus on your public interfaces and ensure that these contracts you have to the outside are working as expected. This is way more important than a high-test coverage.
So, what is considered part of the public contract on a Vue.js component?
Your component provides a few ways for the public to engage with it. These should be considered as the test input. This can be properties or user interactions. Now you should fire them at your component and validate the result against the public result: This can be an event or a response in form of a rendered UI.
So, what is not considered part of the public contract on a Vue.js component?
Interactions with the Vuex store, mutations and actions are not considered to be part of the public contract. The same goes for API modules, UI libraries or anything that produces side-effects.
If you are using the vue-test-utils library, there will be the possibility of snapshot tests. These create a snapshot file from a component the first time the test is run. On each following execution the test will assert that the appearance is the same.
What’s good about it?
These tests are almost free in the aspect of effort, because you do not need to define a target structure of how you want your component to look. It helps you to identify rendering regressions and is great for signing-off UI components in terms of appearance.
What’s bad about it?
When taken regularly the snapshot files can get quite large and may need a lot of storage. An even bigger problem is having false positives and negatives, which do happen.
You should start unit testing your Vue.js components now, even if you just cover the public contracts. The implementation is quite cheap and brings great stability results. For even better results consider implementing integration and E2E tests.