Angular 2 TestComponentBuilder无法解析组件

时间:2016-07-12 16:15:19

标签: javascript unit-testing angular mocking

我有一个非常常见/简单的场景。我有一个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

0 个答案:

没有答案