Testing angular 2 apps: Part 1 – Introduction

In this series, I’m going to show you some tips about writing unit tests in Angular 2 with Jasmine framework. Right now, it’s hard to find up-to-date recipes to write unit tests for Angular 2 (version 2.4 exactly). But, I hope that this series will provide you with some materials to get you going.

1. Angular testing module

Angular 2 requires you to import your testing methods from @angular/testing, including Jasmine functions aka describe, beforeEach, it and so on.

import {
  describe,
  expect,
  beforeEach,
  it,
  inject
} from '@angular/core/testing';

But this is not something that you had to memorize. In fact, if you use angular-cli to seed your project which I recommend. You’ll get always the minimal code for unit testing for the unit under test (component or service, etc.). If you run the following command

$ ng generate service user-profile

angular-cli will generate two files for you:user-profile.service.ts and user-profile.service.spec.ts. The .spec file will look like:

import { TestBed, async, inject } from '@angular/core/testing';
import { UserProfileService } from './user-profile.service';

describe('UserProfileService', () => {
   beforeEach(() =>; {
     TestBed.configureTestingModule({
       providers: [UserProfileService]
     });
   });

   it('should ...', inject([UserProfileService], (service: UserProfileService) => {
     expect(service).toBeTruthy();
   }));
});

So what we have here ? We imported some testing utilities from Angular 2, three exactly:

  1. TestBed: which is very similar to NgModule, as it helps to setup dependencies for the defined tests. This dependencies should be passed to .configureTestingModule() and it’ll be used to resolve any dependency.
  2. async: In fact, we need to use async when dependencies involve asynchronous processing (XHR calls)
  3. inject: allow us to inject dependencies at the TestBed level

2. Dependency Injection

As mentioned earlier, We use TestBed to declare dependencies for out test suites. We had to use inject to get dependencies at TestBed level.

   it('should ...', inject([Service], (service: Service) => {
     expect(service).toBeTruthy();
   }));

If you need to get the dependency at component level, you need to use the
component injector which is a property of fixture’s DebugElement.

describe('MyComponent', () => {
   beforeEach(() => {
     TestBed.configureTestingModule({
       declarations: [ MyComponent ],
       providers: [ MyService ]
     });
   });
it('should ...', () => {
    let fixture = TestBed.createComponent(MyComponent);
    let service = fixture.debugElement.injector.get(MyService);
  });

});

WARNING: DON’T CREATE THE SERVICE USING THE CONSTRUCTOR. Don’t think even about it. This is neither safe nor maintainable.

Now, we can refactor the code using Jasmine’s beforeEach function so we don’t repeat this snippet for each spec.

describe('MyComponent', () => {

   let component: MyComponent,
       service: MyService,
       fixture: ComponentFixture<MyComponent>;</pre>

   beforeEach(() => {
     TestBed.configureTestingModule({
       declarations: [ MyComponent ],
       providers: [ MyService ]
     });
   });

   beforeEach(() => {
     fixture = TestBed.createComponent(MyComponent);
     component = fixture.componentInstance;
     service = fixture.debugElement.injector.get(MyService);
   });

   it('should ...', () => {
     expect(service).toBeTruthy();
   });
});

3. Testing coverage

Generally we need to test everything in our application including Pipes, Services, Components and custom classes. Our tests should cover logic written with TypeScript, generated DOM, emitted events, etc.

Hopefully, angular-cli provides a rich test command. In fact, it provide the –cov parameter,  which will generate a test coverage report for your project. Furthemore, if you use a CI server, you can display a nice report using Cobertura plugin for example. You can find below an example:

cobertura-example.png

Thanks for reading! Have any questions? Ping me at @benzid_wael. In the next posts, I’ll show you how to write tests for services, components, etc.