Tom
Tom

Reputation: 8691

Error: <toHaveBeenCalled> : Expected a spy, but got undefined

I am getting an error expected Spy but got undefined in my angular 10 test. I am using Jasmine and Karma. I have mocked the service SpreadsheetService as mockSpreadSheetService. I am calling the its method. I fail to understand why its expecting a spy.

One possible reason i could think of is that mockSpreadSheetService gets created before running the test and we are calling component.ngOnit which possible recreates the component instance. I tried to explicitly create the mockservice after component.ngOnit but it still didnt work.

My question Ideally we should be testing on the mock object. Why is spy needed.

expect(mockSpreadSheetService.loadXML).toHaveBeenCalled();

TestComponent

 let component: SpreadsheetComponent;
  let fixture: ComponentFixture<SpreadsheetComponent>;
  let mockSpreadSheetService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
        imports: [HttpClientTestingModule],
        declarations: [SpreadsheetComponent],
        providers: [{SpreadsheetService, useFactory: () =>   mockSpreadSheetService.Object}]
      })
      .compileComponents();
  }));

  beforeEach(() => {

    mockSpreadSheetService = new Mock<SpreadsheetService>({
      loadXML: () => of(xmlData)
    });

    fixture = TestBed.createComponent(SpreadsheetComponent);
    component = fixture.componentInstance;
    //fixture.detectChanges();

  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should call loadXML when ngOnInit is called', fakeAsync(() => {
   // spyOn(component.spreadsheetService, 'loadXML');
    component.ngOnInit();
    tick();
    expect(mockSpreadSheetService.loadXML).toHaveBeenCalled();
  }));
});

Main component

 ngOnInit(): void {
    this.spreadsheetService.loadXML().subscribe((data) => {
      this.parseXML(data)
        .then((data) => {
          console.log('data is ' , data);
          this.xmlItems = data;
        });
    });
  }

Upvotes: 3

Views: 5560

Answers (1)

Suyash Gupta
Suyash Gupta

Reputation: 26

spy is not correctly created.

Here's how it would look:

let component: SpreadsheetComponent;
  let fixture: ComponentFixture<SpreadsheetComponent>;
  let mockSpreadSheetService;

  beforeEach(async(() => {
    mockSpreadSheetService = jasmine.createSpyObj(['loadXML']);
    mockSpreadSheetService.loadXML.and.returnValue(of());

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [SpreadsheetComponent],
      providers: { provide: SpreadsheetService, useValue: mockSpreadSheetService }
    });

    fixture = TestBed.createComponent(SpreadsheetComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

  }));

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should call loadXML when ngOnInit is called', () => {
    component.ngOnInit();
    expect(mockSpreadSheetService.loadXML).toHaveBeenCalled();
  });
});

Upvotes: 1

Related Questions