我有一个非常常见/简单的场景。我有一个http服务,它调用本地json文件并获取最终将被实际api调用替换的数据。
我想模拟服务并在组件的ngOnInit上编写测试,但它似乎无效。
工厂form.component.ts
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Factory } from './factory';
import { FactoryService } from './factory.service';
@Component({
moduleId: module.id,
selector: 'factory-form',
templateUrl: './factory-form.component.html',
styleUrls: ['./factory-form.component.css'],
providers: [FactoryService]
})
export class FactoryFormComponent implements OnInit {
private model: Factory = new Factory();
countries;
factoryStatuses;
productTypes;
risks;
private errorMessage: string;
private submitted: boolean = false;
private active: boolean = true;
constructor(private factoryService: FactoryService) {
}
ngOnInit(): void {
this.getCountries();
}
private getCountries() {
this.factoryService.getCountry()
.subscribe(countries => this.countries = countries,
error => this.errorMessage = error);
}
onSubmit(): void {
this.submitted = true;
this.factoryService.saveFactory(this.model);
}
}
factory.service.ts
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Factory } from './factory';
import { IDictionary } from '../shared/dictionary';
import { AppSettings } from '../shared/app.constants';
@Injectable()
export class FactoryService {
constructor(private http: Http) {
}
getCountry(): Observable<IDictionary[]> {
return this.http.get(AppSettings.countryUrl)
.map(this.extractData)
.do(data => console.log("get Countries: " + JSON.stringify(data)))
.catch(this.handleError);
}
private extractData(response: Response) {
let body = response.json();
return body || {};
}
private handleError(error: Response) {
console.log(error);
return Observable.throw(error.json().error || "500 internal server error");
}
}
factory.service.mock.ts
import {provide, Provider} from '@angular/core';
import {FactoryService} from './factory.service';
import * as Rx from 'rxjs/Rx';
export class MockFactoryService extends FactoryService{
public fakeResponse: any = [{"id": 1, "name": "uk"}];
public getCountry(): Rx.Observable<any> {
let subject = new Rx.ReplaySubject()
subject.next(this.fakeResponse);
return subject;
}
public setResponse(response: any): void {
this.fakeResponse = response;
}
public getProvider(): Provider {
return provide(FactoryService, { useValue: this });
}
}
工厂form.component.spec.ts
/* tslint:disable:no-unused-varfoiable */
import { By } from '@angular/platform-browser';
import { DebugElement, provide } from '@angular/core';
import {
beforeEach, beforeEachProviders,
describe, xdescribe,
expect, it, xit,
async, inject,
addProviders,
fakeAsync,
tick,
ComponentFixture,
TestComponentBuilder
} from '@angular/core/testing';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { FactoryService } from './factory.service';
import { MockFactoryService } from './factory.service.mock';
import { FactoryFormComponent } from './factory-form.component';
beforeEachProviders(() => [FactoryFormComponent, provide(FactoryService, { useClass: MockFactoryService })]);
describe('When loading the FactoryFormComponent', () => {
var builder;
beforeEach(inject([TestComponentBuilder], (tcb) => {
builder = tcb;
builder.overrideProviders(FactoryFormComponent,
[
{ provide: FactoryService, useClass: MockFactoryService }
])
.overrideTemplate('<h1>fake tempalte</h1>');
}));
it('should call ngOnInit', async(() => {
let component = builder.createAsync(FactoryFormComponent);
console.log("component?" + JSON.stringify(component));
component.then((fixture: ComponentFixture<FactoryFormComponent>) => {
console.log("inside block");
fixture.detectChanges();
var compiled = fixture.debugElement.nativeElement;
expect(fixture.componentInstance.ngOnInit).toHaveBeenCalled();
expect(fixture.componentInstance.MockFactoryService.getCountry).toHaveBeenCalled();
}).catch((error) => {
console.log("error occured: " + error);
});;
}));
});
这是输出
12 07 2016 16:54:56.314:INFO [watcher]: Changed file "C:/Projects/ethical_resourcing/src/Ethos.Client/dist/app/factory/factory-form.component.spec.js".
12 07 2016 16:54:56.393:INFO [watcher]: Changed file "C:/Projects/ethical_resourcing/src/Ethos.Client/dist/app/factory/factory-form.component.spec.js.map".
12 07 2016 16:54:56.988:WARN [web-server]: 404: /base/dist/vendor/systemjs/dist/system-polyfills.js.map
LOG: 'component?{"_handler":{"resolved":false}}'
Chrome 51.0.2704 (Windows 7 0.0.0): Executed 1 of 1 SUCCESS (0.108 secs / 0.1 secs)
由于某种原因它的传递,因为它不会进入内部区块。我故意打破了 creatAsync.then()代码,看看会出现什么样的组件价值。
如果有人有更好的建议来嘲笑那个很棒的服务。
更新:我确实尝试过使用templateUrl并覆盖它但没有运气。也许缺少一些基本的东西。
更新2:我使用的是angular-cli,只需拨打 ng test 。