我需要在单元测试中取消订阅吗? [英] Do I need to unsubscribe from subscriptions in my unit tests?

查看:82
本文介绍了我需要在单元测试中取消订阅吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我进行了如下测试:

If I have a test such as the following:

it('should return some observable', async(() => {
  mockBackend.connections.subscribe((mockConnection: MockConnection) => {
    const responseOptions = new ResponseOptions({
      body: JSON.stringify(/* some response */)
    });

    mockConnection.mockRespond(new Response(responseOptions));
  });

  service.getSomeObservable()
    .subscribe(result => {
      expect(result).toBe(/* expected response */);
    });
}));

我是否需要在afterEachafterAll块中取消订阅,以避免出现内存问题?还是会自动将其删除?

Do I need to unsubscribe from the subscription in an afterEach or afterAll block to avoid memory issues? Or will it be automatically removed?

推荐答案

@estus是正确的,您无需退订.

@estus is correct, you do not need to unsubscribe.

tl; dr;

  • 可观察对象/主题对所有订阅者保留引用,直到完成.
  • 具有活动引用的对象无法标记为垃圾回收.基本JS.
  • Http Observables do 完成,当时不接受订阅,并将其释放给GC.

  • Observables/Subjects hold refererences to all subscribers until complete.
  • Objects with active references cannot be marked for Garbage collection. Basic JS.
  • Http Observables do complete, disgarding subscriptions at that time, and freeing them up for GC.

在可观察项/主题"被拆除或完成之前,除非您取消订阅,否则无法进行GC的 订阅.

Until the Observable/Subject gets torn down or completes, no subscription can be GC'd unless you unsubscribe.

考虑以下简单的Angular TestBed设置:

Consider this simple Angular TestBed setup:

describe(`DataService`, () => {
  let service: DataService;
  let httpMock: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        DataService,
      ]
    });

    service = TestBed.get(DataService);
    httpMock = TestBed.get(HttpTestingController);
  });

  it(`should get a response`, () => {
    service.getData().subscribe(response => {
      expect(response).toBeTruthy();
    });
  });

对于通过角度HttpClient发出的Http请求,Observable将完成,并且对GC的对订户的引用也将释放.在如上所示的常规Angular Jasmine测试中-即使您的Observable尚未完成-每次调用beforeEach时都会重置由service引用的DataService对象,并且旧的DataService对象将丢失所有引用,并标记为GC.一旦发生这种情况,DataService中的Observable/Subject引用的所有订阅都将丢失对它们的引用,并且也将对其进行GC处理.

In the case of an Http request via the Angular HttpClient, the Observable will complete, and the references to Subscribers will be released for GC. In the case of general Angular Jasmine Testing as shown above--even if you had an Observable that didn't complete--the DataService object being referenced by service gets reset every time beforeEach is called, and the old DataService object will have lost all references and is marked for GC. Once that happens, any subscriptions referenced by the Observable/Subject in the DataService will lose references to them, and they'll be GC'd as well.

请记住,Observables会发生内存泄漏,因为它们会保留对所有订阅服务器的引用,除非订阅服务器取消订阅.它们将继续对它们及其包含的函数具有有效的引用,并且直到主题/可观察对象被销毁之前,才能将它们标记为GC.如果主题继续存在,并且您继续添加订阅者(例如同一订阅​​者的新实例),则会继续向内存中添加一堆旧的未使用对象.

Remember, memory leaks happen with Observables because they retain references to all Subscribers and unless the Subscriber unsubscribes. They will continue to have valid references to them and their containing functions, and cannot be marked for GC until The Subject/Observable is destroyed. If the Subject continues to live and you keep adding subscribers--such as new instance of the same Subscriber--you will keep adding a bunch of old, unused objects to memory.

这篇关于我需要在单元测试中取消订阅吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆