Front-end Development
How-tos & Guides
7 min read

Guide to testing Angular apps

Learn the basics of testing Angular apps, including guide for unit testing, component testing, and end-to-end testing.

Obumuneme Nwabude
Published December 1, 2022
Tired of flaky end-to-end tests?
Create fast and reliable tests for anything that runs in a browser.
Learn more

Introduction

Angular is one of the most popular frameworks for creating web applications. Angular is designed to be a “batteries included” framework, meaning that many of the things you’d need to build and maintain a web application are included with the framework.

In this article, we’ll cover how you can start implementing the following types of tests in Angular:

Let’s get started!

Setting up our Angular project

When you initialize an Angular project with the ng new command, Angular defaults to setting up Jasmine which is a popular library for unit testing. However Angular does support the use of alternative unit testing libraries. For example, you could instead opt to use Jest, a unit testing library developed by Facebook which is very popular in the React community. In this article, we’ll assume that you’re using the default library: Jasmine.

Unit tests are small bits of code that test a very specific behavior, such as the behavior of a single function in your app. In addition to being short, unit tests also tend to run very quickly; typically orders of magnitude faster than an API or integration test.

Unit tests in Angular always live in files that end in .spec.ts and can be run via the ng test command. The ng test command is responsible for finding the unit tests that should run, and executing it using the unit test library that you installed.

Throughout this article, we will be testing a sample web application which is a simple calculator. Before we start creating tests, let’s first create the Angular calculator project.

You should already have Angular installed, but if not, you can install it via Angular’s homepage. Once it’s installed, run the following command in your terminal to generate the example calculator app.

ng new calculator --style=scss --routing=false

Open the newly generated calculator project in your favorite editor. Open the src/app/app.component.ts file. It contains the AppComponent class with a single member, title.

title = 'calculator';

Open the accompanying src/app/app.component.spec.ts file that Angular had auto-created. It contains a describe block with 3 it tests. This is how we write test code - inside it blocks, inside a describe block.

The it block represents a stand-alone feature being tested - i.e. a single unit test. This block always has at least one expect statement. These expect statements are the actual tests. We are expecting our code to behave in a particular way.

The top-level describe block is just a way to organize your unit tests. For example, maybe you have a number of unit tests you want to create for one component. Each unit test would be in a separate it block, but they all could live inside a single describe block. The describe and it blocks take a string as its first argument. This string is meant to describe the block, and is output in the logs when the tests run.

Let’s see this in action. Run ng test and observe that all 3 of these tests pass immediately. The ng test command will output the test results in the terminal as well as in a dedicated browser instance.

How to write unit tests in Angular

As we mentioned previously, unit tests are meant to be fast and simple. In Angular, you can write unit tests for a TypeScript class, utility methods, pipes, services, or guards.

To create an Angular unit test, we’re going to complete the following steps:

For the sake of simplicity, our calculator will only support addition. Let’s create an add method inside the main src/app/app.component.ts file. Include the following in the body of AppComponent.

add = (a: number, b: number) => a + b;

Your src/app/app.component.ts file should now look like the following:

import { Component } from "@angular/core";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"],
})
export class AppComponent {
  title = "calculator";
  add = (a: number, b: number) => a + b;
}

Now that we’ve created the add method, let’s test it.

We already have a spec file (src/app/app.component.spec.ts). We just have to write the it block for addition. Append the following it block to the existing 3 blocks in src/app/app.component.spec.ts:

it("should add two numbers", () => {
  const fixture = TestBed.createComponent(AppComponent);
  const app = fixture.componentInstance;
  expect(app.add(1, 2)).toEqual(3);
});

Your src/app/app.component.spec.ts file should now look like the following:

import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [AppComponent]
    }).compileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'calculator'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app.title).toEqual('calculator');
  });

  it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.nativeElement as HTMLElement;
    expect(compiled.querySelector('.content span')?.textContent).toContain(
      'calculator app is running!'
    );
  });

  it('should add two numbers', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app.add(1, 2)).toEqual(3);
  });
});

If you return to the terminal where you launched ng test or to the dedicated browser instance that the command opened, you will see that while editing, the tests (and results) were being auto-updated.

All 4 tests should pass this time.

Component testing in Angular

An Angular component is a TypeScript class and an HTML template working together. As such, testing an Angular component involves ensuring that both parts are coupled as intended.

Because the component involves both the template and the TypeScript class, we need a way to control both in the test code. This explains why somewhere in the spec file (src/app/app.component.spec.ts), we have the following code

await TestBed.configureTestingModule({
  declarations: [AppComponent],
}).compileComponents();

The above code compiles and prepares AppComponent. Consequently, inside the it blocks, we can obtain a working instance of AppComponent with the following:

const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;

The obtained instance will then work as if the component was actually in the browser at run time.

Angular comes with an @angular/core/testing package. This testing package provides utility classes and functions for component testing. TestBed is the most used class from this package, and is used in the snippets above.

The difference between unit and component testing is that unit testing, as the name implies, tests just a given piece (unit) of logic. Whereas component testing is for checking the entire Angular component. When you create components in Angular, write tests for the core functionalities of those components. By default, the Angular CLI generates the spec file for each component’s TypeScript file, as you generate that component. So this makes component testing easier.

To test Angular components:

How to write end-to-end tests in Angular

End-to-End tests are the topmost level type of test. They supersede component testing. End-to-End tests (e2e) target full-blown applications. They ensure that the entire app works as it should.

An Angular app is made up of several components. After testing each component, write end-to-end tests (e2e) for the entire Angular app. E2E checks that the Angular components appropriately interact with each other to create a full browser page.

Reflect is a powerful tool for building end-to-end tests for Angular apps. Unlike the examples above, Reflect does not require any code. Instead, to create a test in Reflect, you simply record your actions using Reflect’s built-in recorder. Those actions automatically get translated into an end-to-end test that you can run any time.

One of the nice things about this tool is that it’s very easy to hook it up to run automatically whenever you deploy your code. For more information on how to use Reflect and integrate it with CI tools like Jenkins and CircleCI, checkout the Reflect homepage.

Conclusion

Testing is essential for a business’ success. When you write tests for your products, you minimize crashes from code changes. Testing should not be cumbersome. Reflect makes end-to-end test easy across all frameworks, Angular inclusive.

In this article, you’ve learned how to write unit, component, and end-to-end tests in Angular. Most especially, you’ve learned how to use Reflect with Angular. Cheers to the many Angular e2e tests you will run with Reflect!

Happy Coding.

Get started with Reflect today

Create your first test in 2 minutes, no installation or setup required. Accelerate your testing efforts with fast and maintainable test suites without writing a line of code.

Copyright © Reflect Software Inc. All Rights Reserved.