Write a Unit Test
Explore writing unit tests for Angular components with Jasmine. Understand how to use TestBed to create isolated test environments, run change detection cycles, and make assertions on component properties and rendered HTML content. This lesson teaches you how to validate component creation and data binding effectively to improve application reliability.
We'll cover the following...
Testing an Angular component
Let’s take a look at the files created when we generate a new component using the Angular CLI. For example, we could use the generate command to create an ArticlesIndex component:
When Angular generates the component, it creates four files:
Angular generates a basic test for us in articles-index.component.spec.ts.
At the end of the file, there is an example test that Angular has written for us. The toBeTruthy method tests that our result is true when interpreted as a boolean. All values are considered to be truthy except for the following falsy values: false, 0, -0, "", null, NAN, and undefined. So, in this case, our component variable will be truthy if it was created successfully.
Try running your first Angular component test in the code widget below:
Remember that our goal in unit testing is to isolate the component or part of the system that we want to test. In this case, Angular provides us with a tool called TestBed, which we can use to do just that. TestBed lets us mount the component in a controlled environment. Instead of running the whole application, we fire up the component we are testing in isolation. Let’s take a look at the first beforeEach block:
First, we call configureTestingModule, where we declare the component we want to set up in the TestBed. At this stage, we haven’t created the component yet; we are simply declaring it so that we can use it later. Next, we call the compileComponents method, which runs asynchronously. Angular compiles our component by pulling in the external HTML and CSS files. In some setups, Angular compiles components on the fly; however, we need to do this explicitly in our test setup. We have used the async/await notation for this method so that our test runner will wait for the component to compile before moving on to the next step.
Now, let’s take a look at the next beforeEach block:
This is the block where we create our component under test. The fixture variable gives us access to the component we are testing. It provides us with some helpful ways to interact with the test component. The fixture also gives us direct access to the component via the componentInstance property. We need to call the fixture.detectChanges method, which triggers an Angular fixture.detectChanges function at the start of most tests. We might also need to rerun it during the test if we make data changes, which we want to see reflected in the component template.
Testing HTML content
Now, let’s look at our second example, where we render some data in the component and make assertions about the resulting HTML:
Let’s break down what’s happening here.
-
On line 23, we use the
fixtureto give us access to thedebugElement. ThedebugElementis designed as a testing helper, making it easy to inspect the HTML rendered by the component. -
On line 31, we set the
articlesvariable on the component, filling it with an array of dummy data. We provide twoarticleseach with atitleanddescriptionproperty. -
On line 41, we run the
fixture.detectChangesmethod, which triggers an Angular change detection cycle and re-renders the component HTML. We need to run this method so that thearticlesdata array we loaded will be reflected in the DOM. -
On line 43, we use the
queryAllmethod to write a query that selects all the HTML elements with a class oftitle:
We can use the debugElement.query method to select the first matching element, or we can use the debugElement.queryAll method to select all matching elements. Then, we need to use the By.css method to run our CSS selector. Then we finally make our test expectations using the selected data:
We used the .nativeElement property to access the underlying HTML element. This allows us to make our expectations about the .textContent of those elements.
Coding exercise
In this exercise, we test an Angular component called DrinksMenuComponent. The component has a property called drinks, defined on line 14, which stores an array of objects representing drinks from a menu. The component will render an HTML list of drinks and their prices.
In the file drinks-menu.component.spec.ts, your task is to complete the test should display the drink names.
On line 43, write code to select the HTML elements with the class of name and assert that they contain the correct values:
You can see the solution to the problem above in the code snippet below:
We now know how to use TestBed to test an Angular component. The TestBed allows us to mock dependencies and query the rendered HTML.