清理组件时出现 TypeError
TypeError during cleanup of component
我想弄清楚为什么我的 angular 组件测试失败了。查看堆栈跟踪,问题似乎来自 _subscriptions
对象是 undefined
这一事实,但我不明白这是怎么可能的,也不知道为什么会这样。这是我在测试失败时得到的完整堆栈:
HeadlessChrome 79.0.3945 (Windows 10.0.0): Executed 8 of 26 SUCCESS (0 secs / 0.191 secs)
ERROR: 'Error during cleanup of component', Object{component: PlayerComponent{...}, _subscriptions: Object{routerSubscription: ...}}, stacktrace: TypeError: Cannot read property 'unsubscribe' of undefined
TypeError: Cannot read property 'unsubscribe' of undefined
at http://localhost:9876/_karma_webpack_/src/app/player/player.component.ts:58:29
at Array.map (<anonymous>)
at PlayerComponent.ngOnDestroy (http://localhost:9876/_karma_webpack_/src/app/web-player/web-player.component.ts:57:36)
at callProviderLifecycles (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28212:1)
at callElementProvidersLifecycles (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28171:1)
at callLifecycleHooksChildrenFirst (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28153:1)
at destroyView (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38603:1)
at callWithDebugContext (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:39716:1)
at Object.debugDestroyView [as destroyView] (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:39313:1)
at ViewRef_.destroy (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:27128:1)}
HeadlessChrome 79.0.3945 (Windows 10.0.0): Executed 9 of 26 SUCCESS (0 secs / 0.207 secs)
ERROR: 'Error during cleanup of component', Object{component: PlayerComponent{router: Object{navigate: ..., events: ...}, _subscriptions: Object{routerSubscription: ...}}, stacktrace: TypeError: Cannot read property 'unsubscribe' of undefined
TypeError: Cannot read property 'unsubscribe' of undefined
at http://localhost:9876/_karma_webpack_/src/app/web-player/web-player.component.ts:58:29
at Array.map (<anonymous>)
at PlayerComponent.ngOnDestroy (http://localhost:9876/_karma_webpack_/src/app/web-player/web-player.component.ts:57:36)
at callProviderLifecycles (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28212:1)
at callElementProvidersLifecycles (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28171:1)
at callLifecycleHooksChildrenFirst (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28153:1)
at destroyView (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38603:1)
at callWithDebugContext (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:39716:1)
at Object.debugDestroyView [as destroyView] (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:39313:1)
那是我的 PlayerComponent.ts:
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { Router, RouterEvent, NavigationStart } from '@angular/router';
import { combineLatest, Subscription } from 'rxjs';
export class WebPlayerComponent implements OnInit, OnDestroy {
private _subscriptions: { [key: string]: Subscription } = {};
constructor(
private readonly router: Router
) { }
ngOnInit() {
this._subscriptions ["routerSubscription"] = this.router.events.subscribe((event: RouterEvent) => {
// other logic here
});
}
ngOnDestroy() {
Object.keys(this._subscriptions).map((key) => {
this._subscriptions[key].unsubscribe();
});
}
}
这是对它的测试:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
describe('PlayerComponent', () => {
let component: PlayerComponent;
let fixture: ComponentFixture<PlayerComponent>;
beforeEach(async(() => {
let router = {
navigate: jasmine.createSpy(),
events: {
subscribe: jasmine.createSpy(),
unsubscribe: jasmine.createSpy()
}
};
TestBed.configureTestingModule({
providers: [
{ provide: Router, useValue: router },
],
declarations: [ PlayerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PlayerComponent);
fixture.detectChanges();
component = fixture.componentInstance;
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
您确定 routerSubscription 是唯一的订阅吗?是否有另一个订阅发生可能导致取消订阅未定义?尝试导入 RouterTestingModule 而不是存根。 angular.io/api/router/testing/RouterTestingModule 尝试将 console.log(key) 放在取消订阅之前,以查看它试图取消订阅的密钥。
我想弄清楚为什么我的 angular 组件测试失败了。查看堆栈跟踪,问题似乎来自 _subscriptions
对象是 undefined
这一事实,但我不明白这是怎么可能的,也不知道为什么会这样。这是我在测试失败时得到的完整堆栈:
HeadlessChrome 79.0.3945 (Windows 10.0.0): Executed 8 of 26 SUCCESS (0 secs / 0.191 secs)
ERROR: 'Error during cleanup of component', Object{component: PlayerComponent{...}, _subscriptions: Object{routerSubscription: ...}}, stacktrace: TypeError: Cannot read property 'unsubscribe' of undefined
TypeError: Cannot read property 'unsubscribe' of undefined
at http://localhost:9876/_karma_webpack_/src/app/player/player.component.ts:58:29
at Array.map (<anonymous>)
at PlayerComponent.ngOnDestroy (http://localhost:9876/_karma_webpack_/src/app/web-player/web-player.component.ts:57:36)
at callProviderLifecycles (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28212:1)
at callElementProvidersLifecycles (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28171:1)
at callLifecycleHooksChildrenFirst (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28153:1)
at destroyView (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38603:1)
at callWithDebugContext (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:39716:1)
at Object.debugDestroyView [as destroyView] (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:39313:1)
at ViewRef_.destroy (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:27128:1)}
HeadlessChrome 79.0.3945 (Windows 10.0.0): Executed 9 of 26 SUCCESS (0 secs / 0.207 secs)
ERROR: 'Error during cleanup of component', Object{component: PlayerComponent{router: Object{navigate: ..., events: ...}, _subscriptions: Object{routerSubscription: ...}}, stacktrace: TypeError: Cannot read property 'unsubscribe' of undefined
TypeError: Cannot read property 'unsubscribe' of undefined
at http://localhost:9876/_karma_webpack_/src/app/web-player/web-player.component.ts:58:29
at Array.map (<anonymous>)
at PlayerComponent.ngOnDestroy (http://localhost:9876/_karma_webpack_/src/app/web-player/web-player.component.ts:57:36)
at callProviderLifecycles (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28212:1)
at callElementProvidersLifecycles (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28171:1)
at callLifecycleHooksChildrenFirst (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:28153:1)
at destroyView (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:38603:1)
at callWithDebugContext (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:39716:1)
at Object.debugDestroyView [as destroyView] (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/fesm2015/core.js:39313:1)
那是我的 PlayerComponent.ts:
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { Router, RouterEvent, NavigationStart } from '@angular/router';
import { combineLatest, Subscription } from 'rxjs';
export class WebPlayerComponent implements OnInit, OnDestroy {
private _subscriptions: { [key: string]: Subscription } = {};
constructor(
private readonly router: Router
) { }
ngOnInit() {
this._subscriptions ["routerSubscription"] = this.router.events.subscribe((event: RouterEvent) => {
// other logic here
});
}
ngOnDestroy() {
Object.keys(this._subscriptions).map((key) => {
this._subscriptions[key].unsubscribe();
});
}
}
这是对它的测试:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
describe('PlayerComponent', () => {
let component: PlayerComponent;
let fixture: ComponentFixture<PlayerComponent>;
beforeEach(async(() => {
let router = {
navigate: jasmine.createSpy(),
events: {
subscribe: jasmine.createSpy(),
unsubscribe: jasmine.createSpy()
}
};
TestBed.configureTestingModule({
providers: [
{ provide: Router, useValue: router },
],
declarations: [ PlayerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PlayerComponent);
fixture.detectChanges();
component = fixture.componentInstance;
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
您确定 routerSubscription 是唯一的订阅吗?是否有另一个订阅发生可能导致取消订阅未定义?尝试导入 RouterTestingModule 而不是存根。 angular.io/api/router/testing/RouterTestingModule 尝试将 console.log(key) 放在取消订阅之前,以查看它试图取消订阅的密钥。