我正在测试订阅路由器参数的组件。每个测试通过,一切正常。但如果我查看控制台,我会看到一个错误:
Error during cleanup of component ApplicationViewComponent
localConsole.(anonymous function) @ context.js:232
你知道为什么会这样吗?
我尝试从ngOnDestroy()方法中删除unsubscribe(),错误消失。
karma / jasmine是否自动支持unsubscribe()?
这是组件和测试
零件
import { Component,OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs/Rx' import { AppService } from 'app.service'; @Component({ selector: 'app-component',templateUrl: './app.component.html',styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { private routeSubscription: Subscription; // Main ID public applicationId: string; constructor( private route: ActivatedRoute,private _service: AppService ) { } ngOnInit() { this.routeSubscription = this.route.params.subscribe(params => { this.applicationId = params['id']; this.getDetails(); this.getList(); }); } getDetails() { this._service.getDetails(this.applicationId).subscribe( result => { console.log(result); },error => { console.error(error); },() => { console.info('complete'); } ); } getList(notifyWhenComplete = false) { this._service.getList(this.applicationId).subscribe( result => { console.log(result); },() => { console.info('complete'); } ); } ngOnDestroy() { this.routeSubscription.unsubscribe(); } }
组件规范文件
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { async,fakeAsync,ComponentFixture,TestBed,tick,inject } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { HttpModule } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import { Router,ActivatedRoute } from '@angular/router'; // Components import { AppComponent } from './app.component'; // Service import { AppService } from 'app.service'; import { AppServiceStub } from './app.service.stub'; let comp: AppComponent; let fixture: ComponentFixture<AppComponent>; let service: AppService; let expectedApplicationId = 'abc123'; describe('AppComponent',() => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [AppComponent],imports: [RouterTestingModule,HttpModule],providers: [ FormBuilder,{ provide: ActivatedRoute,useValue: { params: Observable.of({id: expectedApplicationId}) } },{ provide: AppService,useClass: AppServiceStub } ],schemas: [ NO_ERRORS_SCHEMA ] }) .compileComponents(); })); tests(); }); function tests() { beforeEach(() => { fixture = TestBed.createComponent(AppComponent); comp = fixture.componentInstance; service = TestBed.get(AppService); }); /* * COMPONENT BEFORE INIT */ it(`should be initialized`,() => { expect(fixture).toBeDefined(); expect(comp).toBeDefined(); }); /* * COMPONENT INIT */ it(`should retrieve param id from ActivatedRoute`,async(() => { fixture.detectChanges(); expect(comp.applicationId).toEqual(expectedApplicationId); })); it(`should get the details after ngOnInit`,async(() => { spyOn(comp,'getDetails'); fixture.detectChanges(); expect(comp.getDetails).toHaveBeenCalled(); })); it(`should get the list after ngOnInit`,'getList'); fixture.detectChanges(); expect(comp.getList).toHaveBeenCalled(); })); }
service.stub
import { Observable } from 'rxjs/Observable'; export class AppServiceStub { getList(id: string) { return Observable.from([ { id: "7a0c6610-f59b-4cd7-b649-1ea3cf72347f",name: "item 1" },{ id: "f0354c29-810e-43d8-8083-0712d1c412a3",name: "item 2" },{ id: "2494f506-009a-4af8-8ca5-f6e6ba1824cb",name: "item 3" } ]); } getDetails(id: string) { return Observable.from([ { id: id,name: "detailed item 1" } ]); } }
接受的解决方案不是最佳解决方案,它解决了测试设置不正确的问题。
出现“组件清理期间出错”错误消息,因为调用ngOnDestroy()时,this.routeSubscription未定义。发生这种情况是因为从未调用过ngOnInit(),这意味着您从未订阅过该路由。如Angular testing tutorial中所述,在第一次调用fixture.detectChanges()之前,组件未完全初始化。
因此,正确的解决方案是在调用createComponent之后立即将fixture.detectChanges()添加到您的beforeEach()块。它可以在您创建夹具后随时添加。这样做将确保组件完全初始化,组件清理也将按预期运行。