如何在Angular中测试是否已取消所有订阅?

3

基本上,我想检查在调用ngOnDestroy后是否有任何有效的订阅。目前,该代码将所有订阅收集到组件的属性数组中,并在ngOnDestroy上取消订阅。我很容易忘记将新创建的订阅添加到此数组中。希望编写一个测试来帮助我消除这种情况。


1
你可以尝试使用 https://github.com/cartant/rxjs-tslint-rules#rules 和 https://blog.angularindepth.com/rxjs-avoiding-takeuntil-leaks-fb5182d047ef。 - Hsuan Lee
谢谢!这个链接对我的知识很有用(: 我没有找到如何强制取消订阅。 - IAfanasov
上面评论中的博客链接已经失效。该文章的规范链接为:https://ncjamieson.com/avoiding-takeuntil-leaks/ - cartant
2个回答

4

我不确定您是想测试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完成其应有的职责,结束所有已在此组件的公共可观察对象上启动的订阅。
然而,如果您关心后者,则唯一检查杂散订阅的方法是通过monkey-patching rxjs中的Observable。这个库很好地实现了这一点(我不是相关人员)。使用它编写一个测试将非常简单:
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();
  });
  ...

谢谢,Dmitriy!第二个解决方案看起来就是我需要的。我会尝试它。 - IAfanasov

0

你可以做一个简单的技巧,在每个订阅中增加服务中的一个值,并在每个取消订阅中减少它,然后您可以检查如果值为0,则没有任何订阅保持活动状态

mysubscription.subscribe( data => { this.myService.myValue++;})
mysubscription.unsubscribe( data => { this.myService.myValue--;})

1
同样的问题我也遇到过 - 在调用subscribe方法时很容易忘记这个值。 - IAfanasov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接