2

I have a service like :

login.service.ts

import { Injectable } from 'angular2/core';
import { Http, Response, Headers } from 'angular2/http';
import { Config } from '../common/config';

@Injectable()
export class LoginService {

    constructor(public http: Http) { }
    response: JSON;
...

    getAuthenticate( username, password ) {
        let headers = new Headers();
        const REST_BASE_URL = Config.GET_REST_BASE_URL;
        let query = '?userid=' + username + ' +&action=authenticate&password=' + password;
        headers.set('Accept', 'application/json');
        return this.http.get(REST_BASE_URL + query, {
        headers: headers
         }).map((res: Response) => res.json());
    }
}

I need to write a test for e.g. getAutenticate() method. No idea how I should inject that Http (mock-up vs real rest service). Here is my starting point:

import { it, describe, expect, inject, beforeEachProviders} from 'angular2/testing';
import {Http} from 'angular2/http';
import { LoginService } from './login.service';

class MockLoginService extends LoginService {
    // todo something
}

describe('login service', () => {
    beforeEachProviders(() => [
        provide(TestService, {useClass: MockLoginService}), Http
  ]);

    // beforeEachProviders(() => [LoginService, Http]);
    it('should find credentials', inject([LoginService], (myService:MockLoginService) => {
        console.log('HERE ', myService.getAutenticate('user1', 'pass1'));
        expect(true).toBe(true);
    }));
});

What would be a good approach ?

ng-flo
  • 293
  • 4
  • 17

1 Answers1

4

In fact to test your LoginService you need to mock its dependencies and not the service itself. In this case, you need to replace the XHRBackend class by the MockBackend one.

beforeEachProviders(() => {
    return [
  HTTP_PROVIDERS,
  provide(XHRBackend, { useClass: MockBackend }),
        HttpService
    ];
});

Then you can inject the XHRBackend and subscribe on its connections property to intercept requests and return your own responses.

Here is a sample with a service called HttpService:

it('test HTTP service', inject([XHRBackend, HttpService, Injector], (mockBackend, httpService, injector) => {
    mockBackend.connections.subscribe(
        (connection: MockConnection) => {
            connection.mockRespond(new Response(
                new ResponseOptions({
                    body: ['some content']
                })));
    });

    httpService.getMethod().subscribe(
        items => {
            expect(items).toEqual(['test']);
        },
        () => {
            console.log('error');
        });
}));

The HttpService could be the following:

@Injectable()
export class HttpService {
  constructor(private http:Http) {
  }

  getMethod() {
    return this.http.get('/test').map(res => res.json());
  }
}
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thank you again, Thierry, I tried your example : the problem is I get the error: Failed: httpService.getMethod is not a function ... – ng-flo Apr 11 '16 at 13:10
  • And you have a `getMethod` method on your `HttpService` class? – Thierry Templier Apr 11 '16 at 13:29
  • 1
    So I have no idea what I did but: based on your answer I tried https://github.com/krimple/angular2-webpack-demo-routing-and-http . I had same issue . Then I looked at the Service and I noticed there is an import there import 'rxjs/add/operator/map'; I added that to teh service and worked ! – ng-flo Apr 11 '16 at 13:42
  • Great! Pleased to hear that! Yes you need to import it explicitly. See this question: http://stackoverflow.com/questions/34515173/angular-2-http-get-with-typescript-error-http-get-map-is-not-a-function-in/34515276#34515276. – Thierry Templier Apr 11 '16 at 13:44
  • I come from a slightly different background (ExtJS) and this seem strange to me : to have something into the class you want to test in order to be able to test it ...mmm. – ng-flo Apr 11 '16 at 13:45
  • What do you mean by "have something into the class you want to test"? – Thierry Templier Apr 11 '16 at 13:51