在清理组件期间使用unsubscribe错误测试Angular组件

前端之家收集整理的这篇文章主要介绍了在清理组件期间使用unsubscribe错误测试Angular组件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在测试订阅路由器参数的组件。每个测试通过,一切正常。但如果我查看控制台,我会看到一个错误

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()块。它可以在您创建夹具后随时添加。这样做将确保组件完全初始化,组件清理也将按预期运行。

猜你在找的Angularjs相关文章