mercredi 19 juillet 2017

Angular4 service test with Http call returning result

I am having trouble trying to mock the response of an Angular4's service function in order to test the service. I have setup a test module, used TestBed to configure the testing module and provided / mocked all required providers and imports in order to get the test module working as expected.

Unfortunately, when I run the test it would seem that my mockBackend connections call is not returning as expected as I get the following error:

Failed: Cannot read property 'userProfile' of undefined

userProfile is an object stored as a property on the response object, so if this is empty I can only assume I am not getting a response back correctly.

Here is my code:

The service ( I have only included the function i am trying to test)

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map'
import { Router } from "@angular/router";

@Injectable()
export class AuthenticationService {
    public token: string;
    public authLevel: number;

    constructor(
        private _http: Http,
        private _router: Router
    ) {
        // set token if saved in local storage
        const currentUser = JSON.parse(localStorage.getItem('currentUser'));
        if(currentUser) {
            this.token = currentUser && currentUser.token;
            this.authLevel = currentUser.userGroup.authLevel;
        } else {
            this._router.navigate(['/login']);
        }
    }

    login(email: string, password: string): Observable<boolean> {
        return this._http.post('/login', { email: email, password: password })
            .map((response: Response) => {
                // login successful if there's a jwt token in the response
                let responseJSONParsed = response.json();
                let token = responseJSONParsed.token;
                this.authLevel = responseJSONParsed.extras.userProfile.userGroup.authLevel;
                if (token) {
                    // set token property
                    this.token = token;

                    // store username and jwt token in local storage to keep user logged in between page refreshes
                    localStorage.setItem('currentUser', JSON.stringify({...responseJSONParsed.extras.userProfile, token: token}));

                    // return true to indicate successful login
                    return true;
                } else {
                    // return false to indicate failed login
                    return false;
                }
            });
    }

And here is the testing module:

import { HttpModule, Http, BaseRequestOptions, RequestOptions, ResponseOptions, Response } from '@angular/http';
import { Router } from "@angular/router";
import { MockBackend } from '@angular/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { async, inject, TestBed} from "@angular/core/testing";
import { AuthenticationService } from "../../services/authentication.service";
import { mockLoginResponse} from "../../mockData/responses/mockLoginResponse";

describe('Service: Authentication Service', () => {
    let router = {
        navigate: jasmine.createSpy('navigate')
    };

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                AuthenticationService,

                MockBackend,
                BaseRequestOptions,
                {
                    provide: Http,
                    useFactory: (backend, options) => new Http(backend, options),
                    deps: [MockBackend, BaseRequestOptions]
                },
                { provide: Router, useValue: router }
            ],
            declarations: [

            ],
            imports: [
                HttpModule,

            ],
        });
    });

    it('should construct', async(inject([AuthenticationService, MockBackend], (authenticationService, mockBackend) => {
        expect(authenticationService).toBeDefined();
    })));

    describe('login method', () => {
        const mockResponse = JSON.stringify(mockLoginResponse.successful);

        it('should return an observable', async(inject([AuthenticationService, MockBackend], (authenticationService, mockBackend) => {
            mockBackend.connections.subscribe(conn => {
                conn.mockRespond(new Response(new ResponseOptions({ body: JSON.stringify(mockResponse) })));
            });

            const result = authenticationService.login();

            result.subscribe((response) => {
                expect(response).toEqual(1);
            });

        })));
    });
});

And the mockResponse from the login function:

export let mockLoginResponse = {
    successful : {
        "success": true,
        "extras": {
            "userProfile": {
                "email": "test12",
                "username": "test12",
                "userToAccount": {
                    "_id": "5968db040e132d4f53a1019a",
                    "user": "5968db040e132d4f53a10199",
                    "userGroup": "596605a46c792e49ecfc936c",
                    "account": "59676afff29a55b615b9ab1a",
                    "__v": 0,
                    "default": true
                },
                "account": {
                    "address": "blahblah",
                    "name": "blahblah",
                    "_id": "59676afff29a55b615b9ab1a"
                },
                "userGroup": {
                    "__v": 1,
                    "authLevel": 0,
                    "name": "superadmin",
                    "_id": "596605a46c792e49ecfc936c"
                }
            }
        },
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1OTY4ZGIwNDBlMTMyZDRmNTNhMTAxOTkiLCJpc3MiOiJkZWdvdWxkLWxvZ2luLmRldiIsInBlcm1pc3Npb25zIjoiIiwiaWF0IjoxNTAwNDY5MjMwfQ.H7v2wJXhrHvGw4mMi3SjF5seQMQV5Nu7pgrL1wqETzs"
    }
};

Can anyone see where I am going wrong here?

Thanks

Aucun commentaire:

Enregistrer un commentaire