Behavior Driven Development Using Karma And Jasmine In Angular 2

Writing unit tests for applications is always given a secondary preference due to the time and the cost. Writing tests for logic for the front end script is more complex and time consuming. Thus, it is often left out. However, as more and more tools are coming, writing unit tests is becoming more easy and manageable.

In this article, we will learn how can we write unit tests for the components in Angular 2. Angular 2 is a powerful and fast JavasSript library, which is used to develop complex front-end Applications for the Web and mobiles.

TDD is Test Driven Development, where the developers write tests that drive the software development. It focuses more on each and every unit test for every function, as it doesn't matter what it does.

BDD is Behavior Driven Development that focuses on the functionalties in a story telling format. We write the behavior & specification that then drives our software development.

You should already have node.js installed tools that we will use.



Jasmine is a Behavior-Driven Development (BDD) framework to test JavaScript code. It does not depend on any other JavaScript frameworks. 

npm install --save-dev jasmine

(Install Jasmine from NPM, if not already installed).

 

Karma is a JavaScript test runner, which is created by AngularJS team

npm install --save-dev karma

(Install Karma from NPM, if not already installed).
Thus, you can see that we will use 2 tools. Jasmine is for writing our Tests and Karma is for running the Tests.

Lets get started,

Hope, you have your Angular 2 Application ready. If not, goto my previous article to quickly setup a new Angular 2 Application.
Note

Run NPM install, if you are downloading this article source code before proceding.

Important

Inside your Applictaion, there must be a karma.conf.js file, which has all the settings to run the Test. This config file tells Karma Test running which test framework to use (jasmine in our case), where our test files (*.spec.ts) are located etc.

Step 1

Under the app folder, create a folder Math and then create 3 files.
  •  ..app/math
  • math.component.ts (Component TypeScript file)
  • math.component.html (Component View HTML file)
  • math.component.spec.ts (Component Test file)
All Test files will have .spec.ts naming convention. 

math.component.html
  • textboxes 2 way binding, using ngmodel with the varaible num1 and num2
  • Button that calls CallEvent, when clicked.
    1. <h1>  
    2.     Math Components  
    3. </h1>  
    4.    Number 1 : <input type=text size=20 [(ngModel)] ="num1">  
    5.    Number 2 : <input type=text size=20 [(ngModel)] ="num2">  
    6. <input type=button value="Multiply" (click)="CallEvent('MULTIPLY');">  
    7. <input type=button value="Multiply" (click)="CallEvent('ADD');">  
    8.    <br>  
    9.     Output : {{result}}  
    10. </h1>  
math.component.ts
  • num1 and num2 are declared as number.
  • Callevent calls Add or Multiply method depending on an action.
  • Add and Multiply method. These two methods will be tested by us.
    1. import {  
    2.     Component  
    3. } from '@angular/core';  
    4. @Component({  
    5.     selector: 'my-math',  
    6.     templateUrl: './math.component.html'  
    7. })  
    8. export class MathComponent {  
    9.     num1: number = 0;  
    10.     num2: number = 0;  
    11.     result: number = 0;  
    12.     private CallEvent(action) {  
    13.         switch (action) {  
    14.             case 'MULTIPLY':  
    15.                 this.result = this.Multiply();  
    16.             case 'ADD':  
    17.                 this.result = this.Add();  
    18.         }  
    19.     }  
    20.     private Multiply() {  
    21.         return this.num1 * this.num2;  
    22.     }  
    23.     private Add() {  
    24.         return this.num1 + this.num2;  
    25.     }  
    26. }  
Finally, our Test file will look, as shown below.

math.component.spec.ts 
  1. import {  
  2.     TestBed,  
  3.     async  
  4. } from '@angular/core/testing';  
  5. import {  
  6.     HttpModule  
  7. } from '@angular/http';  
  8. import {  
  9.     MathComponent  
  10. } from './math.component';  
  11. import {  
  12.     FormsModule  
  13. } from '@angular/forms';  
  14. describe('MathComponent', () => {  
  15.     beforeEach(() => {  
  16.         TestBed.configureTestingModule({  
  17.             declarations: [  
  18.                 MathComponent  
  19.             ],  
  20.             imports: [FormsModule, HttpModule]  
  21.         });  
  22.         TestBed.compileComponents();  
  23.     });  
  24.     it('should multiply 2 numbers', async(() => {  
  25.         const fixture = TestBed.createComponent(MathComponent);  
  26.         const app = fixture.debugElement.componentInstance;  
  27.         app.num1 = 10;  
  28.         app.num2 = 20;  
  29.         let result = app.Multiply();  
  30.         expect(result).toEqual(200);  
  31.     }));  
  32.     it('should add 2 numbers', async(() => {  
  33.         const fixture = TestBed.createComponent(MathComponent);  
  34.         const app = fixture.debugElement.componentInstance;  
  35.         app.num1 = 10;  
  36.         app.num2 = 20;  
  37.         let result = app.Add();  
  38.         expect(result).toEqual(30);  
  39.     }));  
  40. });  
Now, let's see our test file in detail.
  1. The test suite should begin with describe(..).
  2. Inside the describe(..) method, all the Tests of the math component are written.
  3. beforeEach method runs code before each Test. Thus, in this case, it initializes our module and configures our test.
  4. it(...) is used to create your test. 
The test follows 3 simple rules
  1. Arrange
    Setup everything needed for the running the tested code. This includes any initialization of dependencies, mocks and data needed for the test to run.
    1. const fixture = TestBed.createComponent(MathComponent);  
    2. const app = fixture.debugElement.componentInstance;  
  2. Action
    Invoke the code.
    1. app.num1 = 10;  
    2. app.num2 = 20;  
    3. let result = app.Multiply();  
  3. Assert
    Specify the pass criteria for the test, which fails it, if not met.
    1. expect(result).toEqual(200);  
    Now, we are ready to run our Tests.
STEP 2

Open the command prompt and run from your Angular 2 folder.



I hope I was able to explain how to run Tests, using Jasmine and Karma in Angular 2.Thanks.