How to unit test code inside subscribe for Angular7 unit test case

Roshni joshi picture Roshni joshi · Apr 25, 2019 · Viewed 9.1k times · Source

I want to unit test and get coverage for all code but i am not able to get coverage for code present inside subscribe I am able to spy service and function but inside subscribe i am not able to unit test and get code coverage . following is Angular 7 code .

LoadListData(type) {
    this.itemListEnvName = [];
    if (type === 'EnvirnmentList') {
      this.environmentBookingService.getBookedEnv()
        .subscribe(
          (environmentBookingsData: EbEnvironmentBooking[]) => {
            if (environmentBookingsData.length > 0) {
              this.itemListEnvNameList = environmentBookingsData;
              this.itemListEnvName = [];
              this.itemListEnvNameList.forEach(element => {
                const obj = {};
                obj['id'] = element['environmentId'];
                obj['itemName'] = element['environmentName'];
                this.itemListEnvName.push(obj);
                this.generateCheckDisable = false;
              });
            } else {
              this.generateCheckDisable = true;
            }
          },
          (error) => {
            this.showMessage('No Response From Delivery DB API');
          }
        );
    } else {

      this.showMessage('No Response From Delivery DB API');
    }


  }

and code inside unit test case is like

 it('should call getBookedEnv service ', function () {
    const service = TestBed.get(EnvironmentBookingService); // get your service
    spyOn(service, 'getBookedEnv').and.callThrough(); // create spy
    component.LoadListData('EnvirnmentList');
    expect(service.getBookedEnv).toHaveBeenCalledWith();

  });

How to unit test code inside subscribe i.e.

if (environmentBookingsData.length > 0) {
              this.itemListEnvNameList = environmentBookingsData;
              this.itemListEnvName = [];
              this.itemListEnvNameList.forEach(element => {
                const obj = {};
                obj['id'] = element['environmentId'];
                obj['itemName'] = element['environmentName'];
                this.itemListEnvName.push(obj);
                this.generateCheckDisable = false;
              });
            } else {
              this.generateCheckDisable = true;
            }

Answer

dmcgrandle picture dmcgrandle · Apr 25, 2019

You need to mock the service and have it return an Observable. I have put together a simple example in a StackBlitz to show one way to approach this with your code.

Things to note in the StackBlitz:

  • I mock the service with a spyObject, so there is no need to spy on the service later.
  • In this spyObject I set the return value of the internal function getBookedEnv() to be an Observable - this allows the code within the subscribe to be executed.
  • For any real testing you should replace the empty object currently returned by the getBookedEnv() to some reasonably mocked data.
  • note the providers array and where I replaced the service with the spy object.

Here is the describe from that StackBlitz:

describe('BannerComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  const envBookingServiceSpy = jasmine.createSpyObj('EnvironmentBookingService', {
    getBookedEnv: of({/* mock environmentBookingsData here */})
  });


  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ MyComponent ],
      providers: [
        { provide: EnvironmentBookingService, useValue: envBookingServiceSpy },
      ]
    })
    .compileComponents();
  }));

  beforeEach(async(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
  }));

  it('should call getBookedEnv service ', function () {
    const service = TestBed.get(EnvironmentBookingService); // get your service
    // spyOn(service, 'getBookedEnv').and.callThrough(); // create spy
    component.LoadListData('EnvirnmentList');
    expect(service.getBookedEnv).toHaveBeenCalledWith();
  });
});

I hope this helps give you an idea of how to start testing inside the subscribe of your method.