我是否需要在单元测试中取消订阅订阅?

9 unit-testing jasmine karma-jasmine angular

如果我有如下测试:

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 */);
    });
}));
Run Code Online (Sandbox Code Playgroud)

我是否需要取消订阅afterEachafterAll阻止订阅以避免内存问题?还是会被自动删除?

end*_*der 15

@estus 是正确的,您不需要取消订阅。

tl;博士;

  • Observables/Subjects 持有对所有订阅者的引用,直到完成。
  • 不能将具有活动引用的对象标记为垃圾收集。基础JS。
  • Http Observables确实完成了,当时忽略了订阅,并将它们释放给 GC。

  • 在 Observable/Subject 被拆除或完成之前,除非您取消订阅,否则无法对订阅进行 GC

考虑这个简单的 Angular TestBed 设置:

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();
    });
  });
Run Code Online (Sandbox Code Playgroud)

Http通过 Angular发出请求的情况下HttpClient,Observable 将完成,对 Subscriber 的引用将被释放以供 GC 使用。在如上所示的一般 Angular Jasmine 测试的情况下——即使你有一个没有完成的 Observable——每次调用时都会重置DataService被引用的对象,旧对象将丢失所有引用并被标记对于 GC。一旦发生这种情况,Observable/Subject 中引用的任何订阅都将丢失对它们的引用,并且它们也将被 GC 处理。servicebeforeEachDataServiceDataService

请记住,Observable 会发生内存泄漏,因为它们保留对所有订阅者的引用,除非订阅者取消订阅。它们将继续拥有对它们及其包含函数的有效引用,并且在 The Subject/Observable 被销毁之前不能被标记为 GC。如果主题继续存在并且您不断添加订阅者——例如同一订阅​​者的新实例——您将不断向内存添加一堆旧的、未使用的对象。