mycomponent.spec.ts类:
let myComponent: MyComponent; let myService: MyService; describe('myComponent',() => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [MyComponent],providers: [ {provide: MyService,useClass: MockMyService} // **--passing Mock service** ] }).compileComponents() .then(() => { myComponent = TestBed.createComponent(MyComponent).componentInstance; myService = TestBed.get(MyService); console.log(myService.getData()); }); }); it('should get the mock data',() => { myComponent.ngOnInit(); //-----------> seems like myComponent is not defined at this place,how to resolve this error expect(myComponent.data).toBe(DATA_OBJECT); }); });
下面是MyComponent:
@Component({ selector: 'pm-catalogs',templateUrl: './catalog-list.component.html' }) export class MyComponent implements OnInit { public data: IData[]; constructor(private _myService: MyService) { } public ngOnInit(): void { this._myService.getData() .subscribe( data => this.data = data // error => this.errorMessage = <any>error ); } }
下面是模拟服务
export const DATA_OBJECT: IData[] = [ { 'Id': 1,'value': 'abc' },{ 'Id': 2,'value': 'xyz' }]; @Injectable() export class MockMyService { public getData(): Observable<IData[]> { return Observable.of(DATA_OBJECT); } }
我是Angular2测试的新手,当myComponent.ngOnInit()在我的spec类中调用myService.getData()方法时,我希望myService.getData返回DATA_OBJECT
请帮助我实现这一目标.
解决方法
问题是异步beforeEach被错误地实现,这导致竞争条件.
在beforeEach块中执行.compileComponents().then(()=> {…})导致延迟代码执行,然后回调至少一个tick.它块永远不会等待并在有机会被分配之前访问myComponent变量.
当测试没有失败时,这种竞争条件会变得不那么明显,也会变得更加危险.相反,当之前的测试中的每个测试影响当前测试中的变量时,测试可能会变得交叉污染.
.compileComponents()是同步的,除非有使用styleUrls和templateUrl的组件(如上例所示).在这种情况下,它变为异步,应该使用async helper:
// asynchronous block beforeEach(async(() => { TestBed.configureTestingModule({ ... }) .compileComponents(); })); // synchronous block beforeEach(() => { myComponent = ... });
根据经验,如果块可能是异步的,那么块应该使用fakeAsync helper的异步包装.
使用TestBed测试组件类时,它们遵循生命周期并自动调用它们的钩子.不需要手动调用ngOnInit()(如另一个答案所示)并将导致调用挂钩两次.