Angular2/ Жасмин впрыскивают ложный сервис, не вызывая шпионов
Попытка провести модульное тестирование приложения angular2 с использованием жасмина, но когда я пытаюсь внедрить службу, шпионы не реагируют на входящие вызовы.
Тестирование:
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(() => {
TestBed.configureTestingModule({
declarations: [
RoomComponent
],
providers: [
{
provide: Http, useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => {
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) => {
let spy = spyOn(mockRoomService, 'getRooms').and.callThrough();
fixture.detectChanges();
tick();
expect(spy).toHaveBeenCalled(); //Does not return true
expect(component.rooms).toBeDefined();
})));
Проверено, что сами шпионы работают (используя фиктивный сервис и прямой вызов), что они делают, и что компонент вызывает фиктивный сервис, а не реальный, возвращая тестовые данные:
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.
Попробовал впрыскивать MockRoomService прямо. Попытка поставить шпиона на объект RoomService вместо фиктивного объекта. Никто не возвращает, что шпион был вызван.
Макет Сервис:
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<Room[]> {
console.log("mock service reached");
return new Promise((resolve, reject) => {
resolve(this.testData);
});
}
...
Реальный Сервис:
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<Room[]> {
console.log("real service reached");
return this.http.get('api/rooms/get')
.toPromise()
.then(res => res.json() as Room[]);
}
...
Составная часть:
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 => { this.rooms = room;
console.log(this.rooms); }
);
}
...
Помогите?
1 ответ
Вы получаете неправильный экземпляр RoomService
поставщик.
it('should have rooms after getRooms', inject([RoomService], fakeAsync((mockRoomService: MockRoomService) => {
let componentMockRoomService = fixture.debugElement.injector.get(RoomService);
console.log(mockRoomService instanceof RoomService); // true
console.log(componentMockRoomService instanceof RoomService);// false
mockRoomService
это экземпляр от корневого провайдера, тогда как вам нужно проверить класс, соответствующий вашему компоненту
так вот ваш тест
let componentMockRoomService = fixture.debugElement.injector.get(RoomService);
let spy = spyOn(componentMockRoomService, 'getRooms').and.callThrough();