How to unit test unsubscribe function in angular
I had exactly the same problem, here's my solution:
component.ts:
private subscription: Subscription;//...ngOnInit(): void { this.subscription = this.route.paramMap.subscribe((paramMap: ParamMap) => { // ... });}ngOnDestroy(): void { this.subscription.unsubscribe();}
component.spec.ts:
let dataMock;let storeMock: Store;let storeStub: { select: Function, dispatch: Function};let paramMapMock: ParamMap;let paramMapSubscription: Subscription;let paramMapObservable: Observable<ParamMap>;let activatedRouteMock: ActivatedRoute;let activatedRouteStub: { paramMap: Observable<ParamMap>;};beforeEach(async(() => { dataMock = { /* some test data */ }; storeStub = { select: (fn: Function) => of((id: string) => dataMock), dispatch: jasmine.createSpy('dispatch') }; paramMapMock = { keys: [], has: jasmine.createSpy('has'), get: jasmine.createSpy('get'), getAll: jasmine.createSpy('getAll') }; paramMapSubscription = new Subscription(); paramMapObservable = new Observable<ParamMap>(); spyOn(paramMapSubscription, 'unsubscribe').and.callThrough(); spyOn(paramMapObservable, 'subscribe').and.callFake((fn: Function): Subscription => { fn(paramMapMock); return paramMapSubscription; }); activatedRouteStub = { paramMap: paramMapObservable }; TestBed.configureTestingModule({ // ... providers: [ { provide: Store, useValue: storeStub }, { provide: ActivatedRoute, useValue: activatedRouteStub } ] }) .compileComponents();}));// ...it('unsubscribes when destoryed', () => { fixture.detectChanges(); component.ngOnDestroy(); expect(paramMapSubscription.unsubscribe).toHaveBeenCalled();});
This works for me, I hope it will for you too !
Does this look good to you ?
component.mySubscription = new Subscription();spyOn(component.mySubscription, 'unsubscribe');component.ngOnDestroy();expect(component.mySubscription.unsubscribe).toHaveBeenCalledTimes(1);
I figure out a way to make it work.
First of all, I do not create a subscription instance for each subscription, I usually use only one instance of subscription and add into as many subscriptions I need by using me method 'add' that implements a teardownLogic and allows child subscriptions.
private subscriptions: Subscription; //...ngOnInit(): void { this.mySubscription.add( this.store .select(mySelector) .subscribe((value: any) => console.log(value)) );}ngOnDestroy(): void { this.subscriptions.unsubscribe();}
By doing that, in my tests I can rely on the Subscriptions prototype and detects theunsubscribe method calls. In that case after I call the ngOnDestroy.
const spy = spyOn(Subscription.prototype, 'unsubscribe');component.ngOnDestroy();expect(spy).toHaveBeenCalledTimes(1);