Search code examples
angularjasmine

Angular unit test not correctly calling API service method from spy object


I have the following component and spec file, attempting to test a service call that hits an API endpoint and returns a string, based on an id. Based on the employerId I am passing in, I would expect "Enrollment Employer" to be returned and set to employerName. This test is always failing with the error Expected undefined to be 'Enrollment Employer'

I can debug and view the correct employerId being passed in to getEmployerName() but I'm not receiving a response. Am I writing this test correctly?

Spec:

  beforeEach(() => {
    fixture = TestBed.createComponent(EnrollmentComponent);
    component = fixture.componentInstance;
    debugElement = fixture.debugElement;

    employerService = debugElement.injector.get(EmployerService);
    employerSpy = spyOn(employerService, 'getEmployerName').and.callThrough();

    fixture.detectChanges();
  });


  it('should call the employer service and return the employer name', () => {
    component.employerId = 12485;
    component.getEmployerName();
    expect(employerSpy).toHaveBeenCalled();
    expect(component.employerName).toBe('Enrollment Employer');
  })

Component:

  getEmployerName() {
    this.employerService.getEmployerName(this.employerId).subscribe(res => {
      this.employerName = res.empName;
    });
  }

Service:

  getEmployerName(employerId: number) {
    const url = `${this.url}getEmployerName?employerId=${employerId}`
    return this.apiService.request<any>({ url, method: HttpReqMethod.GET })
  }

Solution

  • You can use fakeAsync and flush to wait for the API call.

    it('should call the employer service and return the employer name', fakeAsync(() => {
        component.employerId = 12485;
        component.getEmployerName();
        flush();
        expect(employerSpy).toHaveBeenCalled();
        expect(component.employerName).toBe('Enrollment Employer');
    }));
    

    You can also fake the API call to save time!

     beforeEach(() => {
        fixture = TestBed.createComponent(EnrollmentComponent);
        component = fixture.componentInstance;
        debugElement = fixture.debugElement;
    
        employerService = debugElement.injector.get(EmployerService);
        employerSpy = spyOn(employerService, 'getEmployerName').and.returnValue(of({empName: 'test'}));
    
        fixture.detectChanges();
      });
    
    
      it('should call the employer service and return the employer name', fakeAsync(() => {
          component.employerId = 12485;
          component.getEmployerName();
          flush();
          expect(employerSpy).toHaveBeenCalled();
          expect(component.employerName).toBe('Enrollment Employer');
      }));