angular2/jasmine 注入模拟服务不调用间谍
angular2/jasmine injected mock service not calling spies
尝试使用 jasmine 对 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 对象而不是模拟对象上。也没有 returns 间谍被调用。
模拟服务:
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); }
);
}
...
帮忙?
您获取的 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
是来自根提供商的实例,而您需要测试 class 对应于您的组件
这是你的测试
let componentMockRoomService = fixture.debugElement.injector.get(RoomService);
let spy = spyOn(componentMockRoomService, 'getRooms').and.callThrough();
尝试使用 jasmine 对 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 对象而不是模拟对象上。也没有 returns 间谍被调用。
模拟服务:
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); }
);
}
...
帮忙?
您获取的 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
是来自根提供商的实例,而您需要测试 class 对应于您的组件
这是你的测试
let componentMockRoomService = fixture.debugElement.injector.get(RoomService);
let spy = spyOn(componentMockRoomService, 'getRooms').and.callThrough();