mardi 1 mars 2016

How to spy a service call in Angular2

Following the code example found on Ari Lerner ng-book2, and using Angular 2 beta 7, I'm trying to mock and spy a call to a service unsuccessfully.

This is the main component using the service:

user-list.component.ts

import {Component, OnInit} from 'angular2/core';
import {UserService} from './user.service';
import {IUser} from './user.model';

@Component({
  selector: 'user-list',
  providers: [UserService],
  template: `
    <div *ngFor="#user of users" class="user">
      <span class="username">Username: {{ user.username }}</span><br>
      <span class="email">Email: {{ user.email }}</span>
    </div>
  `
})
export class UserListComponent implements OnInit {
  public users: IUser[];
  private userService: UserService;

  constructor(userService: UserService) {
    this.userService = userService;
  }

  ngOnInit(): void {
    this.userService.getAllUsers().subscribe(
      (users: IUser[]) => {
        this.users = users;
      },
      (error: any) => {
        console.log(error);
      }
    );
  }
}

And this is the service itself.

user.service.ts

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
import {IUser} from './user.model';

@Injectable()
export class UserService {
  private http: Http;
  private baseUrl: string = 'http://ift.tt/1or1gGJ';

  constructor(http: Http) {
    this.http = http;
  }

  public getAllUsers(): Observable<IUser[]> {
    return this.http.get(this.baseUrl)
      .map(res => res.json());
  }
}

In order to test the UserListComponent, I'm trying to mock the UserService and spy its method call getAllUser using the following code:

user-list.component.spec.ts

import {
  describe, 
  expect, 
  it,
  injectAsync,
  TestComponentBuilder,
  ComponentFixture,
  setBaseTestProviders,
} from 'angular2/testing';

import {SpyObject} from 'angular2/testing_internal';

import {
  TEST_BROWSER_PLATFORM_PROVIDERS, 
  TEST_BROWSER_APPLICATION_PROVIDERS
} from 'angular2/platform/testing/browser';

import {provide} from 'angular2/core';

import {UserListComponent} from './user-list.component';
import {UserService} from './user.service';

class SpyUserService extends SpyObject {
  public getAllUsers: Function;
  public fakeResponse: any = null;

  constructor() {
    super(UserService);
    this.getAllUsers = this.spy('getAllUsers').andReturn(this);
  }

  public subscribe(callback) {
    callback(this.fakeResponse);
  }

  public setResponse(data: any): void {
    this.fakeResponse = data;
  }
}

describe('When rendering the UserListComponent and mocking the UserService', () => {

  setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS, TEST_BROWSER_APPLICATION_PROVIDERS);  

  it('should show one mocked user', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {

    let spyUserService = new SpyUserService();
    spyUserService.setResponse([{
      username: 'ryan',
      email: 'ryan@gmail.com'
    }]);

    return tcb
      .overrideProviders(UserListComponent, [provide(UserService, {useValue: spyUserService})])
      .createAsync(UserListComponent)
      .then((fixture: ComponentFixture) => {
        fixture.detectChanges();
        expect(spyUserService.getAllUsers).toHaveBeenCalled();
      });
  }));

});

When using karma to run the test I'm getting the following console error:

Chrome 48.0.2564 (Mac OS X 10.11.3) ERROR
  Uncaught TypeError: Cannot read property 'isSlow' of null
  at /Users/david/apps/sandbox/angular2-testing-cookbook/src/tests.entry.ts:19430

Do anybody know why is this error being thrown or the proper way to mock and spy a service for unit testing an Angular 2 component?

Aucun commentaire:

Enregistrer un commentaire