Roshni joshi
Roshni joshi

Reputation: 88

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

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;
            }

Upvotes: 7

Views: 20513

Answers (2)

dmcgrandle
dmcgrandle

Reputation: 6070

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.

Upvotes: 0

Fabian K&#252;ng
Fabian K&#252;ng

Reputation: 6193

If you want to test the code inside subscribe, you would have to mock your service call and then test the component variables that you are modifying inside subscribe, e.g. this.itemListEnvName and this.generateCheckDisable.

This could look like this:

 it('should call getBookedEnv service ', function () {
    const service = TestBed.get(EnvironmentBookingService); // get your service
    spyOn(service, 'getBookedEnv').and.callFake(() => {
      return of([]); // or return a list of bookings in case you want to test the first part of the if statement 
    });
    component.LoadListData('EnvironmentList');
    expect(service.getBookedEnv).toHaveBeenCalledWith();

    // additional tests that verify the inside of the subscribe (change below in case the mocked service returned something)
    expect(component.itemListEnvName).equalTo([]);
    expect(component.generateCheckDisable).equalTo(false);
  });

Upvotes: 4

Related Questions