This page looks best with JavaScript enabled

Testing Angular App With Karma And Jasmine

 ·  ☕ 8 min read  ·  ✍️ Adesh

What is Unit Testing?

In computer programming, unit testing is a software testing method by which individual units of source code are tested to determine whether they are fit for use. A unit is the smallest possible testable software component. A unit is small, so it is easier to design, execute, record, and analyze test results for than larger chunks of code are. Defects revealed by a unit test are easy to locate and relatively easy to repair.

Some developers underestimate the importance of writing unit tests. What follows are the benefits of unit testing that you may want to consider before forming your own opinion.

Benefits of Unit Testing

Unit testing provides numerous benefits including finding software bugs early, facilitating change, simplifying integration, providing a source of documentation, and many others, which we will look right now.

  • Unit testing reduces the number of bugs very quickly and easily.
  • programmers following the Test-Driven Development (TDD) process claim that unit testing helps them achieve their goals faster, solving problems with less code and better code architecture.
  • It is important to improves the code design and make the code easy to understand by development teams in future.
  • If issues found in unit testing then it is easy to debug that issue because there is a small module in which the developer have to fine the exact code which is defected and fix it.
  • Development is faster. How? If you do not have unit testing in place, you write your code and perform that fuzzy ‘developer test’.
  • Tests can be started at an earlier stage. You don’t have to wait until the GUI is available.

Angular Unit Testing Introduction

It’s easy to get started with unit testing for Angular 2+ apps. If your projects was setup using the Angular CLI, everything will be ready for you to start writing tests using Jasmine as the testing framework and Karma as the test runner. Angular also provides utilities like TestBed and async to make testing asynchronous code, components, directives or services easier.

Let’s see how to start unit testing your angular app.

Creating your Angular App with Karma and Jasmine

Let’s first create your angular app using this command.

1
ng new angular-testing

Once your project is setup, all the dependencies related to Karma and Jasmine have been installed in. your package.json file automatically. Open your package.json file, and notice these dependencies.

karma and jasmine settings in package.json

package.json

If you notice, there are two things mentioned in the above pic, one is Karma and another is Jasmine. Let’s have a brief look into these two keywords.

  • Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it’s suited for websites, Node.js projects, or anywhere that JavaScript can run.

  • Karma is a simple tool that allows you to execute JavaScript code in multiple real browsers. Karma is not a testing framework, nor an assertion library. Karma just launches an HTTP server, and generates the test runner HTML file you probably already know from your favourite testing framework. So for testing purposes you can use pretty much anything you like.

Karma Configuration File

Angular-Cli create one Karma configuration file karma.conf.js in your src directory, Take a look at this config file.

karma configuration file

karma.conf.js

Let’s have a brief introduction of this file to better understand this testing stuff.

  • frameworks: this is where your app testing framework is set. If you want to change to any other testing framework, you can change it here.
  • autoWatch: if this is set to true, the tests run in watch mode. If you change any test and save the file the tests are re-build and re-run.
  • browsers: this is for browser launcher. By default, it is set to Chrome, and you can change it to your preferred browser.

test.ts - Test Entry File

There is a test.ts file generated by Angular-Cli in your project folder. This file is required by karma.conf.js and loads recursively all the .spec and framework files.

test.ts file in angular

test.ts

There are a lot of things mentioned in this file, which we don’t need to change. So, I am not going into the detail of this file. Just remember that, this is the entry file for performing unit tests by Angular Cli.

Finally, karma loads all the tests files of the application matching their names against a regular expression. All files inside our app folder that has spec.ts on its name are considered a test.

Writing Angular Unit Tests

Once your angular-testing app is created, you can now run this simple command to test your freshly created app.

1
ng test

Karma will spin up and run all available tests. This will show following message in your terminal window

ng test command

And open the Karma test screen on the browser.

angular app

Before start writing your test cases, let’s first understand the basics of writing the tests in Jasmine framework. You can read more about writing test cases syntax by clicking here.

1
2
3
4
5
describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  });
});
  • describe function is used to describe the test specs. You can create a group of specs, often called a suite.
  • it is global Jasmine function to define specs, which takes a string and function. A spec should contain one or more expectations that test the state of the code. A spec whose expectations all succeed will be passing and a spec with any failures will fail.
  • expect creates an expectation for a spec. This takes a value, which is called actual.
1
2
3
4
5
6
7
8
describe("The 'toBe' matcher compares with ===", function() {
 it("and has a positive case", function() {
    expect(true).toBe(true);
  });
 it("and can have a negative case", function() {
    expect(false).not.toBe(true);
  });
});
  • matcher implements a boolean comparison between the actual value and the expected value. It is responsible for reporting to Jasmine if the expectation is true or false. Jasmine will then pass or fail the spec.
    • toBe() (line 3) matcher expect the actual value to be === to the expected value.
    • not.toBe() (line 6) invert the matcher following this expect.

Setup And Teardown

  • Sometimes in the real-world application before performing or after performed our test case we need to insert some mock data or we need to do some cleaning activity, for these purposes we have
    • beforeAll - This function is called once before all the specs in the test suite are run.
    • afterAll - This function is called once after all the specs in a test suite are finished.
    • beforeEach - This function is called before each test specs.
    • afterEach - This function is called after each test specs.

Now, let’s start with writing our tests.

Testing a component or app.component

Let’s review our default test file of app component, which is app.component.spec.ts in the app folder.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';

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

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

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

  it('should render title in a h1 tag', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('h1').textContent).toContain('Welcome to angular-testing!');
  });
});

The above tests three things:-

  • app should be created. (line 13-17)
  • app should have title ‘angular-testing’ (line 19-23)
  • should render title in a h1 tag. (line 25-30)

In the beforeEach() function, we’re using the TestBed.configureTestingModule function to create a module environment for testing the component. It’s similar to NgModules, except that in this case we’re creating a module for testing.

beforeEach in angular testing

Now, we have created our first spec using it() function to test whether our component is created or not.

creation spec

Next, we are defining spec for testing our app title using the below it() function.

it() function in angular testing

In the last spec, we are testing whether title is rendering in h1 tag or not.

h1 tag spec

In the above code, you have noticed these keywords like TestBed and fixture. Let’s me explain them briefly here.

Angular Testing Utilities

TestBed is used to configures and initializes environment for unit testing and provides methods for creating components and services in unit tests. TestBed is the primary api for writing unit tests for Angular applications and libraries.

fixture is a wrapper for a component and its template. We can create an instance of a component fixture through the TestBed. Fixture is used for debugging and testing a component.

fixture.detectChanges() triggers a change detection cycle for the component. detectChanges() is used to tell the TestBed to perform data binding. Then the will have the expected title.

fixture.debugElement.nativeElement provides the component’s element. Because the tests are running in a browser, a nativeElement in these tests is always an HTMLElement whose familiar methods and properties you can explore within a test.

Summary

Hopefully this has been a useful introduction to Angular testing for you. If you want to learn more, I recommend you stick first to the official Angular documentation.

Further Reading

What Is .Net Core?

Best Chrome Extensions For Debugging Angular Apps

Update Angular 7 to Angular 8

Share on

Adesh
WRITTEN BY
Adesh
Technical Architect