我试图比Angular团队的quickstart教程测试一个简单(但更复杂 - 看似)。我试过看了十几篇其他文章,但也许是因为"流体"过去6到12个月的ng2框架的性质,现在有相当多的资源似乎已经过时了。
我使用Angular 2版本2.4.10,Typescript,Sinon版本2.1.0和Webpack 2(如果重要的话,也是ag-grid)。
组件代码:
更新了问题,在构造函数中包含了OtherService,我在第一次复制时错过了
import { Component, OnInit } from "@angular/core";
import { GridOptions } from "ag-grid";
import { EventDataService } from "./data-service/event-data.service";
import { OtherService } from "./data-service/other.service";
import { ColumnDefs } from "../shared/event-grid/event-grid-column-defs";
import { Event } from "./event/event.interface";
import { Observable } from "rxjs/Rx";
@Component({
templateUrl: "./event-list.component.html",
styleUrls: ["./event-list.component.scss"]
})
export class EventListComponent implements OnInit {
// grid data & settings
private gridOptions: GridOptions;
private columnDefs: any;
// auto refresh / event-service messaging settings
public loadingEvents: boolean;
// main data array = holds event list displayed by grid
private events: Event[];
// updated question with privateOtherService, which I had missed when I first copied this over
constructor(private eventDataService: EventDataService, private otherService: OtherService) {
// initialize grid
this.gridOptions = <GridOptions>{};
this.gridOptions.columnDefs = ColumnDefs;
// initialize flag to indicate we are waiting for events from service
this.loadingEvents = false;
}
beginPollingLoop(): void {
this.getEvents();
// ... other logic that will repeat the getEvents call periodically...
};
getEvents() {
this.loadingEvents = true;
// treats response from event service as an observable to subscribe to
return this.eventDataService.getEvents()
.subscribe(
(events: Event[]) => { this.events = events; },
(error: any) => // handle errors,
() => {this.loadingEvents = false; });
};
ngOnInit(): void {
// begin polling loop (using defaults) once component loads
this.beginPollingLoop();
}
}
规范代码:
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { expect } from "chai";
import { spy } from "sinon";
import { EventListComponent } from "./event-list.component";
// dependency of component
import { EventDataService } from "./data-service/event-data.service";
import { AgGridModule } from "ag-grid-angular/main";
let component: EventListComponent;
let fixture: ComponentFixture<EventListComponent>;
let spies = {
beginPollingLoop: {}
};
let eventServiceStub = {
getEvents: Observable.from([])
};
describe("EventListComponent", () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [AgGridModule.withComponents([])],
declarations: [ EventListComponent ],
providers: [{ provide: EventDataService, useValue: eventServiceStub }]
});
fixture = TestBed.createComponent(EventListComponent);
component = fixture.componentInstance; // component is undefined
spies.beginPollingLoop = spy(component, "beginPollingLoop");
});
describe("EventListComponent", () => {
describe("When the component initializes", () => {
it("should set loadingEvents to 'false'", () => {
expect(component.loadingEvents).to.be.true;
});
});
describe("when OnInit() runs", () => {
let beginPollingLoop = spy(component, "beginPollingLoop");
expect(beginPollingLoop.called).to.equal(true);
});
});
});
我在我的控制台中遇到的具体错误是&#34; Uncaught TypeError:无法读取属性&#39; beginPollingLoop&#39;未定义&#34;。根据调试器,component
是未定义的。在我的屏幕上,Karma的测试输出错误信息是:&#34; TypeError:无法读取属性&#39;进样器&#39; of null&#34;
我觉得我正在按照文档的说明构建Testbed,所以我只能假设我不能正确地注册我的组件的所有依赖项。这导致我的component
无法正确创建。
谢谢!
答案 0 :(得分:1)
我想出了这个问题。在规范中,component
是“未定义的”,因为当TestBed
尝试创建component
时,它失败了,因为我在EventListComponent
的构造函数中使用了其他服务我的规格中没有考虑到这一点。一旦我意识到这一点,并在我的规范中删除了该服务,该组件创建良好。
这就是问题的根源 - 我只是没有看到它,因为Angular抛出的错误被埋没在它自己的代码深处。而不是像“TestBed无法创建组件:构造函数参数不匹配”或其他有用的东西,我看到与其他事情有关的错误试图使用我认为已成功创建的组件。这使得不清楚组件是否已经创建,并且为什么它已经失败了:我创建的组件没有被提供给构造函数所期望的参数。
所以最终规范看起来像:
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { expect } from "chai";
import { spy } from "sinon";
import { EventListComponent } from "./event-list.component";
// dependency of component
import { EventDataService } from "./data-service/event-data.service";
import { OtherService } from "./data-service/other.service";
let component: EventListComponent;
let fixture: ComponentFixture<EventListComponent>;
let eventServiceStub = {
getEvents: Observable.from([])
};
// forgot this one
let otherServiceStub = {
getStuff: () => {}
};
describe("EventListComponent", () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [ EventListComponent ],
providers: [
{ provide: EventDataService, useValue: eventServiceStub },
{ provide: OtherDataService, useValue: otherServiceStub } // this was missing
]
});
fixture = TestBed.createComponent(EventListComponent);
component = fixture.componentInstance; // component is undefined
});
describe("EventListComponent", () => {
describe("when OnInit() runs", () => {
let beginPollingLoop = spy(component, "beginPollingLoop");
expect(beginPollingLoop.called).to.equal(true);
});
});
});
});