For any AngularJS development company it is a must to work with unit testing on any project, regardless of whether you choose to use a TDD (test-driven development) approach or not, using it will have a lot of advantages.
First, we will briefly mention the advantages of unit testing in this article, and then we will create a full example of angular unit testing using Jasmine and Karma to explain each phase of the process. You can carry out this process to create functional automotive digital solutions.
Benefits of Unit Testing
Let’s go first through the main reasons to use unit testing in your solution.
Improve the design of implementations
A very common mistake among developers is to start coding a feature without thinking about the design. The use of unit testing will cause you to consider and re-think the design, and the effect is even greater if you are using TDD.
Because you already have checks to make sure it is running correctly, with the assurance that you are not adding any bugs, you can easily apply improvements to the code.
Add new features without breaking anything
You should run tests when you implement a new function to ensure that you do not break any other aspect of the application.
There’s a lot more, but these three are already such a major win for every project that they are deal sealers. But let’s list a few more if you’re still not sure.
- Tests are good documentation.
- Tests make developers more confident about their work.
All their advantages can be said to come at a great cost: TIME, but this is entirely false. Compared to the time they will save you later when you are adding new features or making some refactors, all the time that using unit testing can cost you will be minimal. The amount of time spent fixing bugs would be significantly lower than if you don’t use unit testing.
Create an Angular project with jasmine and karma
As the angular team recommends, to create our app, we will use angular-cli. By doing this, the jasmine and karma configuration is resolved for us.
Install and create a new project with angular-cli:
- Install npm -g @angular/cli.
- Ng new angular-unit-testing angular unit-testing
When you create the project all the dependencies get installed among them everything you are going to need to create the tests.
In the image above you can see all the dependencies installed for testing purposes. Let’s go through the more important ones;
jasmine. core- The framework we are going to use to build our tests is Jasmine. To allow us to write different kinds of tests, it has a bunch of features.
karma- For our exams, Karma is a mission runner. It uses a configuration file to set up, among other items, the startup file, the reporters, the testing system, the browser.
The remaining dependencies are primarily reporters for our tests, karma and jasmine tools, and browser launchers.
You just need to run the “ng test” command to run a test. This command will run the tests, open the window, view the console and the browser log, and, more importantly, leave the test running in watch mode.
Let’s take a look at the karma configuration file created by angular-cli.
- Frameworks: This is where jasmine is set up as a system for research. This is the place to do it if you want to use another framework.
- Reporters: This is where the reporters are set up. You can modify or add new ones to them.
- AutoWatch: If this setting is true, the tests are run in watch mode. The tests are re-built and re-run when you alter some tests and save the file.
- Browsers: This is where you set up the browser to run the test. It is Chrome by default, but you can install other browser launchers and use them.
Test entry file
The angular-cli configuration of karma uses the file “test.ts” as the entry point of the tests for the application. Let’s take a look at that file;
- Using all the imports at the start of the file, an environment is generated for running angular tests.
- TestBed is a popular angular-supplied unit testing tool and is initialized in this file.
- Finally, karma loads all of the application’s test files that fit their names against a standard expression. All files that have “spec.ts” in their name within our app folder are considered a test.
Our First test
Let’s build the first test for us. Let’s get this done with our app.component.ts. This component has only the “text” property with the “Angular Unit Testing” value rendered inside the “h1” tag in HTML, which also contains the routing root element and some routing links. To verify that the component actually has that property, let’s create a test file that is actually rendered in HTML.
- All the angular testing tools that we will be using are imported.
- All the dependencies that this element has, we import.
- To start our test block, we use “describe” with the title matching the name of the tested component.
- Before each one, we use an async. The aim of the async is to allow all possible asynchronous code to be finished before it continues.
You need to configure an angular testbed before running any angular test. For the component being evaluated, this allows you to construct an angular environment. It is necessary to include in the testbed any module, component, or service that your tested component needs. Finally, you call the Compile Components function after setting the configuration.
We need to set up a dummy routes module for app.component and use a provider to set the base href, without which the test will not compile because we are setting the routing module and a base href is needed.
In the first test, in the title property, we check that the component actually contains the expected text.
First, we need to have an instance of the app. component, for which we use the angular testbed’s build component function, so we get a fixture object that will allow us to create an instance of that component.
Now that we have an instance of app.component we can check the value in the text property and make jasmine expect to be equal to the expected value.
The second test does something similar, but it checks that the “text” property is rendered by dom.
First, it does the same as the other test, gets the fixture app.component, then executes the detect changes feature, this feature applies changes to the HTML component (in this case we apply the interpolation to the text component property’s DOM).
Then the native element of the compiled HTML is obtained (the HTML rendered by the component).
Finally, we select the ‘h1’ value containing the ‘text’ value and expect the expected value to be present in the selected HTML.
Testing a Form
Let’s see now how to test an angular form. Let’s see first the contact.component HTML;
This is fairly straightforward-no explanation is required for that. Using form controls, this is just a regular angular form. If the form isn’t valid, the submit button is disabled.
Let’s see now, the component of contact. component
It is also quite simple to understand this component. The on submit function simply changes the property submitted to true. The contact form has three validation controls.
Let’s see now, the tests for this component;
Compared to the one we saw before, this test has many differences. We’re going to talk about each of them.
First, there is nothing strange about the import section here, except that we are introducing the “By” that will allow us to choose elements from the DOM.
With the name of the component to be tested, we declare the test block.
We will use some test scoped objects to be created that we will use in various tests that will be initialized in the “before each.”
In order to start the test module, the first part of the ‘beforeEach’ sets all the required dependencies. We have already mentioned the “async” reason for that.
In this case, we are using the promise returned by the “compile components” feature. We assign a value to each of the variables we declare at the beginning when the promise is solved.
- The first test simply requires the component instance to have the “text” property’s expected value.
- The second test expects the property of the ‘submitted’ component to be valid when the function ‘onSubmit’ is called.
- The third test adds the component state to the HTML with the “fixture” object’s “detectChanges” feature, then gets the submit button from the DOM and triggers the click case. We generate a jasmine “spy” on the component’s “onSubmit” feature before all of this. Finally, the spy feature is not supposed to be executed because the button should be disabled as the form is not valid.
- The fourth test sets the invalid component form values and expects the true form property to be incorrect.
- Finally, we set valid values for the form in the fifth test and expect the valid form property to be true.
Before wrapping this article up, let’s see one more thing. When the part we are evaluating utilizes them, we can see how to deal with services.
Testing a component with services
When you are going to test a service component, you need to add the providers to the test module generated in the “before each” as we have already seen. The thing is, you probably don’t want to use the actual services instead, but rather a mocked version, so let’s see how to do that…
First, let’s take a look at the component implementation;
This is a basic component that gets a service’s list of users.
It is not necessary for the actual implementation of the service to get users from anywhere, but let’s see how we build the tests for the mocking part of the implementation of the service.
This test is similar to the examples we saw before with one primary difference, we tell the module in the provider’s declaration of the test module that it should use “UserServiceMock” instead when the “UserService” service is injected. UserServiceMock” is a dummy service we created that returns dummy information in order to run the component tests.”
And that’s all, this is how you should mock your services when testing a component
As you can see, we went through a bunch of features and examples to try to illustrate how to test angular components, as it is very simple and you can perform any kind of test.We hope that this article will help you to understand a little better how to use angular testing tools. Brainvire is an AngularJS development company that creates automotive digital solutions with the latest ideas and features.