How to test multiple sequential calls with Jasmine

时光毁灭记忆、已成空白 提交于 2021-02-07 12:56:39

问题


I am trying to test a function that unsubscribes from all subscriptions:

ngOnDestroy() {
        this.tryUnsubscribe(this.carsSubscription);
        this.tryUnsubscribe(this.partsSubscription);
        this.tryUnsubscribe(this.shopsSubscription);
    }

This is the test I wrote for the function:

it('should unsubscribe from subscriptions ', () => { 
      spyOn(component, "tryUnsubscribe");     
      component.ngOnDestroy();
      expect(component.tryUnsubscribe).toHaveBeenCalledWith(component['carsSubscription']);
      expect(component.tryUnsubscribe).toHaveBeenCalledWith(component['partsSubscription']);
      expect(component.tryUnsubscribe).toHaveBeenCalledWith(component['shopsSubscription']);
    });

The problem:

If I comment out a function call, the tests still passes.

ngOnDestroy() {
        this.tryUnsubscribe(this.carsSubscription);
        //this.tryUnsubscribe(this.partsSubscription);
        this.tryUnsubscribe(this.shopsSubscription);
    }

Only if I comment out all of these function calls, the test fails:

ngOnDestroy() {
        //this.tryUnsubscribe(this.carsSubscription);
        //this.tryUnsubscribe(this.partsSubscription);
        //this.tryUnsubscribe(this.shopsSubscription);
    }

How to properly test this kind of function? What am I doing wrong?


回答1:


I would rewrite your test to the following:

it('should unsubscribe from subscriptions ', () => { 
  const spy = spyOn(component, 'tryUnsubscribe');     
  component.ngOnDestroy();

  // Check how many times the spy was called
  expect(spy).toHaveBeenCalledTimes(3);
});

If you now uncomment one of the tryUnsubscribe calls, the test should fail as the spy was only called twice.

Another approach would be to mock the subscriptions or just set them to a dummy value to test that inside the ngDestroy tryUnsubscribe was called with those 3 component variables:

it('test unsubscribing', () => {
  // Mock values
  component.carsSubscription = Observable.of(1).subscribe(() => {});
  component.partsSubscription = Observable.of(1).subscribe(() => {});
  component.shopsSubscription = Observable.of(1).subscribe(() => {});

  const spy = spyOn(component, 'tryUnsubscribe').and.callThrough();     
  component.ngOnDestroy();

  // Check how many times the spy was called
  expect(spy).toHaveBeenCalledTimes(3);

  // Check arguments
  expect(spy.calls.all()[0].args[0]).toEqual(component.carsSubscription);
  expect(spy.calls.all()[1].args[0]).toEqual(component.partsSubscription);
  expect(spy.calls.all()[2].args[0]).toEqual(component.shopsSubscription);
});

Here is a working stackblitz with the test.




回答2:


It is also possible to check all arguments at once using Jasmine calls.allArgs() method:

expect(spy.calls.allArgs()).toEqual([
  [component.carsSubscription],
  [component.partsSubscription],
  [component.shopsSubscription]
]);

Here is modified Fabian Küng's answer in stackblitz.



来源:https://stackoverflow.com/questions/54420277/how-to-test-multiple-sequential-calls-with-jasmine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!