サービスを使用するAngular 2コンポーネントをテストしようとしています。サービスにはHttpが注入されています。これはテストには興味がありませんので、サービスのメソッドコールを監視してスパイしようとしています。これはAngular 1での作業には慣れていましたが、Angular 2で作業することはできません。エラーは、Httpのプロバイダがありません。私は実際のサービス方法を模倣するのではなく、実際のサービス方法を監視することに興味があります。ジャスミンスパイによる角2コンポーネントテスト "Httpのプロバイダなし!"エラー
私のコンポーネントは次のようになります。
import { Component, OnInit } from '@angular/core';
import { NavBarLink } from '../../models/nav-bar-link';
import { NavBarService } from '../../services/nav-bar/nav-bar.service';
@Component({
selector: 'nav-bar',
providers: [NavBarService],
moduleId: module.id,
templateUrl: 'nav-bar.template.html'
})
export class NavBarComponent {
constructor(private _navBarService: NavBarService) { }
links: NavBarLink[];
getLinks(): void {
this._navBarService.getNavBarLinks().then(data => this.links = data);
}
ngOnInit(): void {
this.getLinks();
}
}
そして、私のサービスは、次のようになります。
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Urls } from '../../constants/urls.constants';
import { NavBarLink } from '../../models/nav-bar-link';
@Injectable()
export class NavBarService {
constructor(private _http: Http,
private _urls: Urls) { }
getNavBarLinks():Promise<NavBarLink[]> {
return this._http.get(this._urls.NAV_BAR_LINKS)
.toPromise()
.then(response => {
let navLinks = [];
for(let navLink of response.json()) {
navLinks.push(new NavBarLink(navLink.id, navLink.description, navLink.route));
}
return navLinks;
})
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
そして最後に私のテストは、この
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Provider } from '@angular/core';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { NavBarComponent } from './nav-bar.component';
import { NavBarService } from '../../services/nav-bar/nav-bar.service';
import { Observable } from 'rxjs/Rx';
let comp: NavBarComponent;
let fixture: ComponentFixture<NavBarComponent>;
let navBarService;
class MockNavBarService extends NavBarService{
constructor() {
super(null, null);
}
}
describe ('NavBarComponent tests',() => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NavBarComponent ],
providers: [ {provide: NavBarService, useClass: MockNavBarService} ]
})
.compileComponents()
.then(createComponent);
}));
it('should call the getNavBarLinks when ngOnInit is called',() => {
comp.ngOnInit();
expect(navBarService.getNavBarLinks).toHaveBeenCalled();
});
});
function createComponent() {
fixture = TestBed.createComponent(NavBarComponent);
comp = fixture.componentInstance;
navBarService = fixture.debugElement.injector.get(NavBarService);
spyOn(navBarService, 'getNavBarLinks').and.returnValue(Promise.resolve([]));
}
この解決策の問題は、あなたのコンポーネントが消費するサービスの依存関係しているモジュールにもたらしているということですコンポーネントテストに複雑さが増します。 NavBarServiceがプロバイダを変更するたびに、NavBarComponentを使用または使用するすべてのテストファイルを更新する必要があります。元のサービスを拡張しないクラスでサービスを嘲笑することで、依存関係の複雑さが根絶されます。これにより、テストをよりきれいにすることができ、サービスを変更した場合に注意を要することが少なくなります。 – pe8ter