Kavya Shetty
Kavya Shetty

Reputation: 315

angular2 jasmine mocked service not used but the actual service called

In my employee specs the actual employee service is getting referred not the mocked one. What could possibly be wrong? Foll. is my code block:-

Employee Component

import { Component, ViewChild, OnInit, Input, ElementRef } from '@angular/core';
import { Http } from '@angular/http';
import { Pipe, PipeTransform } from '@angular/core';

import { SharedHttpService } from "../../shared/services/shared-http.service";
import { EmployeeService } from '../services/employee.service';
import { Broadcaster } from '../../shared/services/broadcaster.service';

declare let $: any;
@Component({
    moduleId: module.id,
    selector: 'employee',
    templateUrl: 'employee.component.html',
    providers: [EmployeeService, SharedHttpService, Broadcaster]
})

export class EmployeeComponent implements OnInit {

    constructor(private EmployeeService: EmployeeService,
        private broadcaster: Broadcaster) {  
    }

    public getAllData(role) {
        this.employeeService.getAllEmployeesApiResponse (role);
    }
}

Employee Service

import { Injectable, Inject } from '@angular/core';
import { Http, Response, Headers } from '@angular/http';
import { RequestOptions } from '@angular/http';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Rx';

import { SharedHttpService } from '../../shared/services/shared-http.service';
import { Broadcaster } from '../../shared/services/broadcaster.service';

@Injectable()

export class EmployeeService implements IEmployeeService {
    constructor(
        private _http: Http, 
        private sharedHttpService: SharedHttpService,
        private broadcaster: Broadcaster) { }

    public getAllEmployeesApiResponse = (role): any => {
        this.sharedHttpService.getAllEmployees(role)
            .subscribe(data =>
                this.broadcaster.broadcast("GetAllEmployees", data),
            err =>
                this.errorHandler.handleError(err)
            );
    }

MockEmployeeService

import { Broadcaster } from '../../shared/services/broadcaster.service';

export class MockEmployeeService implements IEmployeeService {

    constructor(private broadcaster: Broadcaster) { }

    public getAllEmployeesApiResponse = (role): any => {
        let employeeData = JSON.parse('[{"id": 198149,"fullName": "Sean Abrahamsen"},{"id": 198150,"fullName": "Rahyl James"}]}');
        let data = [laborScheduleDay, referenceData];

        this.broadcaster.broadcast("GetAllEmployees", employeeData);
    }
}

EmployeeComponent-spec

import { Component, DebugElement, Optional, ViewChild, OnInit, Input, ElementRef, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Http } from '@angular/http';

import { EmployeeService } from '../services/employee.service';
import { MockEmployeeService } from '../mock/mock-employee.service';

describe('EmployeeComponent Specs', function () {
    let debugElement: DebugElement;
    let component: EmployeeComponent;
    let fixture: ComponentFixture<EmployeeComponent>;

    let EmployeeService: EmployeeService
    let mockEmployeeService: MockEmployeeService

    beforeEach(async(() => {
        mockEmployeeService = new MockEmployeeService(broadcaster);

        TestBed.configureTestingModule({            
            declarations: [EmployeeComponent],
            providers: [
                { provide: EmployeeService, useValue: mockEmployeeService }              
            ]
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(EmployeeComponent);
        component = fixture.componentInstance;

        EmployeeService = TestBed.get(EmployeeService);

        fixture.detectChanges();
    });

    describe("When getAllEmployees is called", () => {
        beforeEach(() => {
            EmployeeService.getAllEmployeesApiResponse = jasmine.createSpy('getAllEmployeesApiResponse');
        });

        it('should call getAllEmployeesApiResponse service', () => {
            component.getAllEmployees("Manager");
            expect(EmployeeService.getAllEmployeesApiResponse).toHaveBeenCalledWith("Manager");
        });
    });
});

Upvotes: 2

Views: 974

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 208994

It's because you have the services declared at the component level

@Component({
  providers: [ ... ]
})

When you declare the mock in the TestBed, this is a module level configuration. The component level provider will always supersede the module level provider.

What you can do though, is override the component level provider

TestBed.configureTestingModule({            
  declarations: [EmployeeComponent]
})
.overrideComponent(EmployeeComponent, {
  set: {
    providers: [
      { provide: EmployeeService, useValue: mockEmployeeService } 
    ]
  }
})
.compileComponents();

Another thing you may want to consider is design. You should consider whether or not the service is really meant to be scoped only to the component. If not, then just declare it at the module level, so it will be a singleton.

Upvotes: 4

Related Questions