基本上,我想检查ngOnDestroy调用后是否有任何活动的订阅。现在,该代码将收集组件属性数组中的所有订阅,并取消订阅ngOnDestroy。我很容易忘记为该数组添加一个新创建的订阅。想要编写一个测试来帮助我消除这种情况。
答案 0 :(得分:1)
不确定是否要尝试测试ngOnDestroy方法是否终止了在公共可观察对象外部启动的订阅,或者是否要尝试查看组件内部是否还有任何杂散的内部订阅。
对于前者,您可以编写如下测试:
it('should end subscriptions when the component is destroyed', () => {
// Setup the spies
const spy = jasmine.createSpy();
const noop = () => {};
// Start the subscriptions
const streams = [component.streamOne$, component.streamTwo$, component.streamThree$];
streams.forEach(stream => stream.subscribe(noop, noop, spy));
// Destroy the component
component.ngOnDestroy();
// Verify the spy was called three times (once for each subscription)
expect(spy).toHaveBeenCalledTimes(streams.length);
});
这将确保ngOnDestroy能够完成应做的工作,并终止在此组件的公共可观察对象上启动的所有订阅。
但是,如果您关心的是后者,那么检查流失订阅的唯一方法是通过在rxjs中猴子修补Observable。 This library does it well(我没有隶属关系)。用它编写测试很简单:
import { setup, track, printSubscribers } from 'observable-profiler';
describe('MyComponent', () => {
beforeAll(() => {
setup(Observable);
});
it('should not have any stray subscriptions', () => {
track();
const fixture = TestBed.createComponent(MyComponent);
fixture.detectChanges();
fixture.destroy()
const subscriptions = track(false);
expect(subscriptions).toBeUndefined();
});
...
答案 1 :(得分:0)
您可以做一个简单的技巧,在每个订阅中增加服务的价值,在每个取消订阅中减少服务的价值,然后检查如果该值为0,那么没有订阅有效
mysubscription.subscribe( data => { this.myService.myValue++;})
mysubscription.unsubscribe( data => { this.myService.myValue--;})
答案 2 :(得分:0)
您可以使用takeUntil()
运算符来代替向数组添加订阅。
这样,您创建了一个Subject
,它将在ngOnDestroy
上产生价值,并一次取消订阅多个订阅
unsubscribeSignal: Subject<void> = new Subject();
ngOnInit() {
firstSubscription = firstObservable
.pipe(
takeUntil(this.unsubscribeSignal.asObservable()),
)
.subscribe(result => {});
secondSubscription = secondObservable
.pipe(
takeUntil(this.unsubscribeSignal.asObservable()),
)
.subscribe(result => {});
thirdSubscription = thirdObservable
.pipe(
takeUntil(this.unsubscribeSignal.asObservable()),
)
.subscribe(result => {});
}
ngOnDestroy(){
this.unsubscribeSignal.next();
// Don't forget to unsubscribe from subject itself
this.unsubscribeSignal.unsubscribe();
}