---
title: Unit testing in Angular2
url: https://blog.octoperf.com/unit-testing-in-angular2/
date: '2016-03-31'
authors:
- gpereira
categories:
- Development
tags:
- Angular
- Unit Test
description: Unit testing a component that uses the Router, in Angular2.
---

# Unit testing in Angular2

## Unit tests in Angular2 with Karma

To follow up on my first [article about Angular2](https://blog.octoperf.com/creating-a-singleton-service-in-angular2/) I want to unit test our *Login* component:

```javascript
import {Component} from 'angular2/core';
import {AuthenticationService} from '../services/authentication';
import {Router} from 'angular2/router';

@Component({
  selector: 'login',
  providers: [ ],
  directives: [ ],
  pipes: [ ],
  styles: [ require('./login.css') ],
  template: require('./login.html')
})
export class Login {
  private credentials: string = '';

  constructor(private authService: AuthenticationService, private router: Router) {
  }

  onSignIn(){
    this.authService.setCredentials(this.credentials);
    this.router.navigate(['Home']);
  }
}
```


The [sample project](https://github.com/angularclass/angular2-webpack-starter) comes with karma configured and some tests already written. 
So it's straightforward to create a new unit test for our component:

```javascript
import {
  it,
  inject,
  injectAsync,
  describe,
  beforeEachProviders,
  TestComponentBuilder
} from 'angular2/testing';

import {Component, provide} from 'angular2/core';
import {AuthenticationService} from '../services/authentication';
import {Router} from 'angular2/router';

import {Login} from './login';

describe('Login', () => {
  beforeEachProviders(() => [
    Login,
    AuthenticationService
  ]);

  it('should set credentials and redirect on sign in', inject([ Login, AuthenticationService, Router], (login, auth, router) => {
    [...]
  }));
});
```

## Mocking services

The hard part is to **mock the *Router* Angular2 service**. Indeed if we do not provide a Router implementation karma fails with the following error:

```sh
FAILED TESTS:
  Login
    ✖ should set credentials and redirect on sign in
      PhantomJS 2.1.1 (Linux 0.0.0)
    Failed: No provider for Router! (Login -> Router)
```

A quick [googling](https://stackoverflow.com/questions/35139882/angular-2-testing-components-with-router) tells us that we need to provide many *Router* related services:

```javascript
beforeEachProviders(() => [
 ROUTER_PROVIDERS,
 provide(APP_BASE_HREF, {useValue: '/'}),
 provide(ROUTER_PRIMARY_COMPONENT, {useValue: Login}),
 provide(ApplicationRef, {useClass: MockApplicationRef}
]);
```

This may be a bit cumbersome in my case, and **I preferred to provide a mock object instead of the real *Router***:
```javascript
describe('Login', () => {
  beforeEachProviders(() => [
    Login,
    AuthenticationService,
    provide(Router, {useValue: jasmine.createSpyObj('Router', ['navigate'])})
  ]);

  it('should set credentials and redirect on sign in', inject([ Login, AuthenticationService, Router], (login, auth, router) => {
    login.secretKey = 'test';
    spyOn(auth, 'setCredentials');
    login.onSignIn();
    expect(config.setCredentials).toHaveBeenCalledWith('test');
    expect(router.navigate).toHaveBeenCalledWith(['Home']);
  }));
});
```

This may be done with any service: **we could have injected a spy *AuthenticationService* object instead of only spying on its `setCredentials()` method**.

Also, I think the syntax to write unit tests is much shorter in Angular2 than in AngularJS.
