The Techies' pub

Angular 2 – Testing

Hope you are all well. This post is about writing unit tests for angular 2 applications. If you are familiar with jasmine(framework) and karma(test runner) you will find this post quite easy to understand. Angular 2 was designed with testability in consideration. So, it becomes rather easy to use classes in ‘angular2/testing’ to write our test cases.

First lets clone the quickstart app from the official site of angular 2 using the below command.

1

git clonehttps://github.com/angular/quickstart angular2testing

Then do an npm install after navigating into the directory.

Now run the below command.

1

npm test

You would see that karma test runner fires up and uses the karma.conf.js file and starts to execute tests automatically.

Okay, Let’s write some code and test cases.

Open up your app.component.ts file and modify it as shown below.

1

2

3

4

5

6

7

8

9

10

import{Component}from'angular2/core';

@Component({

selector:'my-app',

template:'<h1>{{somevar}}</h1>'

})

exportclassAppComponent{

privatesomevar:string='Hello';

}

Then open up app.component.spec.ts file and modify it as shown below.

1

2

3

4

5

6

7

8

9

10

11

12

13

import{AppComponent}from'./app.component';

describe('AppComponent',()=>{

beforeEach(function(){

this.app=newAppComponent();

});

it('should have hello property',function(){

expect(this.app.somevar).toBe('Hello');

});

});

This is the file where we add the test cases. As you can see I have added a simple test case which will check the value of the variable somevar which we have used in app.component.ts. Now go ahead and run npm test. You could see that the test passed.

This is how you write a simple test case for your application.

Testing a service:

Let’s create a service first. Create 2 new files namely service.ts and service.spec.ts as shown below.

1

2

3

4

5

6

7

8

import{Injectable}from'angular2/core';

@Injectable()

exportclassTestService{

getnames(){

return['raja','victor','albert'];

}

}

The test service has a function getnames() which simply returns 3 names.

beforeEach and beforeEachProviders are basically the setup for the tests. You could also see that we are injecting our TestService directly through beforeEach and then creating a reference for it using which we access getnames().

In the specs section I am simply comparing the returned values and also the length of the array.

Now here the service din’t use http; but usually when we write apps we use http requests frequently. So let’s go ahead and mock a backend and see how to write tests.

Mocking

Open up service.ts file again and modify it to look like below.

1

2

3

4

5

6

7

8

9

10

11

import{Injectable}from'angular2/core';

import{Http}from'angular2/http';

@Injectable()

exportclassTestService{

constructor(privatehttp:Http){}

getnames(){

returnthis.http.get('someurl');

}

}

Note that since I am creating a mock backend I am just giving some random string but in an app it would correspond to a real url.

MockBackend and MockConnection are two classes that are shipped with angular2 especially for creating a mock backend for testing purposes.

In the beforeEach setup we just create a backend that will return a repsone ‘hello raja’ to all the http requests being made.

In the specs I have simply made a request to the getnames and I am checking whether the response corresponds to hello raja.

Simply run npm test to see whether our tests go fine so far.

Testing Observables

Observables (Part of reactive extensions) can be tested too. Open up test.spec.ts and add the below lines of code.

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

describe('Observable: basic observable',()=>{

varsomevar;

beforeEach(()=>{

somevar=newObservable(observer=>{

observer.next(1);

observer.next(2);

observer.next(3);

observer.complete();

});

})

//specs

it('should create the expected sequence',done=>{

let expected=[1,2,3],

results=[],

index=0;

somevar

.subscribe(

x=>{

expect(x).toEqual(expected[index++]);

},

x=>results.push('#'),

x=>done()

);

})

});

Its pretty much easy to understand. If you notice I am just creating a new Observable and then pushing values subsequently. In the specs I am just subscribing to the observable and comparing the values with a predefined set of values in the expected array.

Testing Routes:

Let’s see how to test routes. Open up app.component.ts and add the below code.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import{Component}from'angular2/core';

import{RouteConfig}from'angular2/router';

import{Home}from'./home';

import{People}from'./people';

@Component({

selector:'my-app',

template:'<h1>{{hello}}</h1>'

})

@RouteConfig([

{path:'/home',component:Home,name:'Home'},

{path:'/people',component:People,name:'People'},

{path:'/**',redirectTo:['Home']}

])

exportclassAppComponent{

}

I have simply created two routes for home and people respectively. (Make sure to create two files home.ts and people.ts respectively).