Search code examples
angularkarma-runnerionic3angular-promisekarma-coverage

Error in Karma Jasmine Unit testing : "Expected spy VehicleId to have been called"


Could you please help me to resolve the below issue. I am fairly new to Angular and Unit Testing. Service is not returning a promise.

Error: Expected spy fetchVehicleId to have been called.

Component Code Snippet:

async getVehicleId() {
  debugger; 
  try {          
    if(this.selectedId) {
        let data: any = await this.VehicleComposer.fetchVehicleId(this.selectedID); 
        this.vehicleQuantity = data.vehicleCaseQuantity;
        this.vehicleId = data.vehicleId; 
        console.log("return service data",data);
      } 
   }
   catch (err) {
     console.log(err)
   }
}

Service Composer Code Snippet:

fetchVehicleId(selectedID) {       
    let center = this.user.getCenterId();    
    let vehicleURL = this.config.getReceiveVehicleURL(selectedID.Id,selectedID.Number,center);
    return new Promise((resolve, reject) => {
        this.api.put(vehicleIdURL)
          .subscribe(
            data => {  
                this.receivingUnit = data.receivingUnitId;
                resolve(data);                   
            }, error => {
                reject({
                    error: true,
                    errorObj: error
                });
            });                             
        });        
    }

Testing Spec code snippet:

Class MockVehicleComposerService { 
  debugger;
  fetchVehicleId(){  
    console.log("---------"); 
    return Observable.of({}); 
  }
}

describe('VehicleComponent', () => {

  let comp: VehicleComponent;  
  let fixture: ComponentFixture<VehicleComponent>; 
  let mockService: MockVehicleComposerService;

  beforeEach(async(() => {

  mockService = new MockVehicleComposerService();

  TestBed.configureTestingModule({
    declarations: [VehicleComponent],
    imports: [IonicModule.forRoot(VehicleComponent)],
    providers: [{ 
        provide: ReceiveVehicleComposer, 
        useValue: MockVehicleComposerService
    }]
  })      
  .overrideComponent(VehicleComponent, {
    set: {
      template: '<div></div>',
      providers: [{
          provide: ReceiveVehicleComposer,
          useValue: MockVehicleComposerService
      }]
    }
  })
  .compileComponents();
}));


it('getVehicleId', async(() => {
  debugger;
  this.selectedID = { "Number":"123" }
  const app = fixture.componentInstance; 
  let messageSpy = spyOn(mockService, 'fetchVehicleId');
  if(this.selectedID){
    app.getVehicleId();
  }

  expect(messageSpy).toHaveBeenCalled();
}));

Solution

  • You are almost there. Just missing the piece where you actually return the Observable. Here is how I've done this on the past. Hope this helps get you on the right track.

    it('getVehicleId', fakeAsync(() => {
      this.selectedID = { "Number":"123" }
      const app = fixture.componentInstance; 
    
      let messageSpy = spyOn(mockService, 'fetchVehicleId').and.returnVaue(
        Observable.of({});
      );
    
      if(this.selectedID){
        app.getVehicleId();
      }      
    
      fixture.detectChanges();
    
      expect(messageSpy).toHaveBeenCalled();
    }));