Show List

Introduction to Angular Testing

Unit testing is the process of testing the small and isolated code. Jasmine and Karma are used for unit testing the Angular application.

Jasmine

Jasmine is JavaScript testing framework that attempts to describe the tests in a human readable format.

For example if want to test below function:
  addNumbers(firstNum: number, secondNumber: number): number{
    return firstNum + secondNumber;
  }
The Jasmine test code can be as below
describe('HomeComponent Test Suite', () => {

  it('Function addNumbers should return correct sum', () => {
    expect(addNumbers(2,3)).toBe(5);
  });

});
  • The describe function defines a Test Suite, a collection of Tests.
  • The it function defines an individual Test. It can contain one or more expect expression.
  • The expect expression describes an expected behaviour.
  • The matcher is a boolean comparison with the expected value passed in vs. the actual value. In the example .toBe(5) is a matcher expression.
In addition to above specs, Jasmine also provides functions of initial set up for test and cleaning up:
  • beforeAll function is called once before all the tests in the test suite.
  • afterAll function is called once after all the tests in the test suite.
  • beforeEach is called before each test is run.
  • afterEach is called after each test is run.

Matchers

Here are some of the matchers. Detailed list can be viewed at https://github.com/JamieMason/Jasmine-Matchers
expect().nothing()
expect().toBe(expected)
expect().toBeCloseTo(expected, precisionopt)
expect().toBeDefined()
expect().toBeFalse()
expect().toBeFalsy()
expect().toBeGreaterThan(expected)
expect().toBeGreaterThanOrEqual(expected)
expect().toBeInstanceOf(expected)
expect().toBeLessThan(expected)
expect().toBeLessThanOrEqual(expected)
expect().toBeNaN()
expect().toBeNegativeInfinity()
expect().toBeNull()
expect().toBePositiveInfinity()
expect().toBeTrue()
expect().toBeTruthy()
expect().toBeUndefined()
expect().toContain(expected)
expect().toEqual(expected)
expect().toHaveBeenCalled()
expect().toHaveBeenCalledBefore(expected)
expect().toHaveBeenCalledOnceWith()
expect().toHaveBeenCalledTimes(expected)
expect().toHaveBeenCalledWith()
expect().toHaveClass(expected)
expect().toHaveSize(expected)
expect().toMatch(expected)
expect().toThrow(expectedopt)
expect().toThrowError(expectedopt, messageopt)
expect().toThrowMatching(predicate)
expect().withContext(message)

Testing Manually

If we were to run the Jasmine tests manually below are the steps:
  • Create an HTML file and include Jasmine JavaScript and CSS files.
  • Load JavaScript file having the function we are testing
  • Load the Jasmine Test file
  • Tests are executed when the HTML window loads.
<link rel="stylesheet" href="jasmine.css">
<script src="jasmine.js"></script>
<script src="jasmine-html.js"></script>
<script src="boot.js"></script>

<script src="functionToTest.js"></script>
<script src="jasmineTest.js"></script>
These steps are to be repeated if testing on multiple browsers. 

Apparently running the Jasmine Tests manually would be tiresome. This is the reason Karma tool is used the Jasmine tests. 

Karma

Karma launches the browser and runs the Jasmine tests inside them. Karma re-runs the tests automatically when there are changes to the code.

Angular CLI includes Karma in the applications created and handles the Karma configuration for us.

When a component is created using Angular CLI, it also creates the Jasmine test file (ending with .spec.ts). Here is a sample Jasmine test file that got created when a pipe was generated with command "ng g pipe cuberoot"

cuberoot.pipe.spec.ts
import { CuberootPipe } from './cuberoot.pipe';

describe('CuberootPipe', () => {
  it('create an instance', () => {
    const pipe = new CuberootPipe();
    expect(pipe).toBeTruthy();
  });
});

To run all the Jasmine tests in the application, simply run "ng test" command from Angular CLI. It will launch the browser and display the outcome of the tests.

Karma Configuration File

Here is the default Karma configuration file created by Angular CLI

karma.conf.js
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      jasmine: {
        // you can add configuration options for Jasmine here
        // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
        // for example, you can disable the random execution with `random: false`
        // or set a specific seed with `seed: 4321`
      },
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    jasmineHtmlReporter: {
      suppressAll: true // removes the duplicated traces
    },
    coverageReporter: {
      dir: require('path').join(__dirname, './coverage/angular-testing'),
      subdir: '.',
      reporters: [
        { type: 'html' },
        { type: 'text-summary' }
      ]
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    restartOnFileChange: true
  });
};

We can see that Jasmine is selected as the default test framework. Plugins, browsers and other configuration can be changed if required.

Karma uses test.ts file as the entry point of the testing. We wont need to make changes to this file but here is a quick look.

test.ts
// This file is required by karma.conf.js and loads recursively all the .spec and framework files

import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';

declare const require: {
  context(path: string, deep?: boolean, filter?: RegExp): {
    <T>(id: string): T;
    keys(): string[];
  };
};

// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
);

// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().forEach(context);

TestBed is unit testing tool provided by Angular is invoked in this file and used to initialize the test environment. All the test files that have spec.ts in their name are then loaded for test execution.

    Leave a Comment


  • captcha text