title: angular2/jasmine injected mock service not calling spies
body: <p>Attempting to unit test an angular2 app using jasmine, but when I try to inject service, the spies don't pick up on injected calls.</p>
  
  <p>Test suite:</p>
  
  <pre><code>import { TestBed, inject, tick, fakeAsync, ComponentFixture } from '@angular/core/testing';
  import { By } from '@angular/platform-browser';
  import { RouterTestingModule } from '@angular/router/testing';
  
  import { RoomComponent } from './room.component';
  
  import { Room } from './room';
  import { RoomService } from './room.service';
  import { MockRoomService } from '../mock/mock.room.service';
  import { BaseRequestOptions, Http, ConnectionBackend, Response, ResponseOptions } from '@angular/http';
  import { MockBackend } from '@angular/http/testing';
  
  ...
  
  beforeEach(fakeAsync(() =&gt; {
  TestBed.configureTestingModule({
    declarations: [
      RoomComponent
    ],
    providers: [
      {
        provide: Http, useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) =&gt; {
          return new Http(backend, defaultOptions);
        },
        deps: [MockBackend, BaseRequestOptions]
      },
      RoomService,
      {provide: MockBackend, useClass: MockBackend},
      {provide: BaseRequestOptions, useClass: BaseRequestOptions}
    ],
    imports: [
      RouterTestingModule
    ]
  })
  .overrideComponent(RoomComponent, {
    set: {
      providers: [{provide: RoomService, useClass: MockRoomService}]
    }
  })
  
  ...
  
  it('should have rooms after getRooms', inject([RoomService], fakeAsync((mockRoomService: MockRoomService) =&gt; {
    let spy = spyOn(mockRoomService, 'getRooms').and.callThrough();
    fixture.detectChanges();
    tick();
    expect(spy).toHaveBeenCalled(); //Does not return true
    expect(component.rooms).toBeDefined();
  })));
  </code></pre>
  
  <p>Tested that spies themselves work (using mock service and a direct call) which they do, and that the component calls the mock service rather than the real one, returning the test data:</p>
  
  <pre><code>LOG: 'ngInitified'
  PhantomJS 2.1.1 (Windows 7 0.0.0): Executed 6 of 21 (skipped 3) SUCCESS (0 secs / 1.156 secs)
  LOG: 'method reached'
  PhantomJS 2.1.1 (Windows 7 0.0.0): Executed 6 of 21 (skipped 3) SUCCESS (0 secs / 1.156 secs)
  LOG: 'mock service reached'
  PhantomJS 2.1.1 (Windows 7 0.0.0): Executed 6 of 21 (skipped 3) SUCCESS (0 secs / 1.156 secs)
  LOG: [Object{_id: '12', gitrepo: 'repository', channel: 'slack channel'}, Object{_id: '42', gitrepo: 'newrepo', channel: 'dev'}]
  PhantomJS 2.1.1 (Windows 7 0.0.0): Executed 6 of 21 (skipped 3) SUCCESS (0 secs / 1.156 secs)
  PhantomJS 2.1.1 (Windows 7 0.0.0) Component: Room should have rooms after getRooms FAILED
      Expected spy getRooms to have been called.
  </code></pre>
  
  <p>Have tried injecting MockRoomService straight. Have tried putting the spy on a RoomService object instead of a mock object. Neither returns that the spy was called.</p>
  
  <p>Mock Service:</p>
  
  <pre><code>import { Injectable } from '@angular/core';
  import { Http } from '@angular/http';
  import { Room } from '../room/room';
  
  @Injectable()
  export class MockRoomService {
      testData: Room[] = [{"_id":"12","gitrepo": "repository", "channel": "slack channel"}, {"_id":"42","gitrepo": "newrepo", "channel": "dev"}];
  
      constructor(http: Http) { }
  
      getRooms(): Promise&lt;Room[]&gt; {
          console.log("mock service reached");
          return new Promise((resolve, reject) =&gt; {
              resolve(this.testData);
          });
      }
  
  ...
  </code></pre>
  
  <p>Real Service:</p>
  
  <pre><code>import { Room } from './room';
  import { Http, Headers, RequestOptions } from '@angular/http';
  
  import 'rxjs/add/operator/toPromise';
  
  import { Injectable } from '@angular/core';
  
  @Injectable()
  export class RoomService {
      constructor (private http: Http) {}
  
      getRooms(): Promise&lt;Room[]&gt; {
          console.log("real service reached");
          return this.http.get('api/rooms/get')
          .toPromise()
          .then(res =&gt; res.json() as Room[]);
      }
  
  ...
  </code></pre>
  
  <p>Component:</p>
  
  <pre><code>import { Component, OnInit } from '@angular/core';
  import { Router } from '@angular/router';
  
  import { Room } from './room';
  import { RoomService } from './room.service';
  
  @Component({
    selector: 'app-room',
    templateUrl: './room.component.html',
    styleUrls: ['./room.component.css'],
    providers: [RoomService]
  })
  export class RoomComponent implements OnInit {
    title = 'Repos and Channels';
    rooms: Room[] = [];
    constructor(
      private roomService: RoomService,
      private router: Router,
      ) {}
  
    ngOnInit() {
      console.log("ngInitified");
      this.getRooms();
    }
  
    getRooms() {
      console.log("method reached!");
      this.roomService.getRooms()
        .then(room =&gt; { this.rooms = room;
          console.log(this.rooms); }
      );
    }
  
  ...
  </code></pre>
  
  <p>Help?</p>