Caleb Seadon
Caleb Seadon

Reputation: 724

Angular unit test failing with error .catch is not a function

I have the following snippet of code that is part of a Component that is working fine the browser. But when I run my Karma/Jasmine unit test it's failing.

Code:

const request = this.queryQueue.pipe(switchMap(() => this.loadAppointments().catch(e => {
  return new Array<Appointment>();
})));

request.subscribe(
  newAppointments=> {
    this.appointments = this.myData.concat(newAppointments);
  }
);

Notes:

loadAppointments

loadAppointments(): Observable<Appointment[]> {
  this.isLoading = true;
  return this.webApiService.getAppointments(this.getSearchDto(), this.appointments.length, 20);
}

Goals:

Error:

TypeError: _this.loadAppointments(...).catch is not a function
    at SwitchMapSubscriber.eval [as project] (webpack:///./src/app/components/appointments/appointments.component.ts?:72:117)
    at SwitchMapSubscriber._next (webpack:///./node_modules/rxjs/_esm5/operators/switchMap.js?:94:27)
    at SwitchMapSubscriber.Subscriber.next (webpack:///./node_modules/rxjs/_esm5/Subscriber.js?:97:18)
    at Subject.next (webpack:///./node_modules/rxjs/_esm5/Subject.js?:66:25)
    at AppointmentsComponent.refresh (webpack:///./src/app/components/appointments/appointments.component.ts?:84:25)
    at AppointmentsComponent.set [as day] (webpack:///./src/app/components/appointments/appointments.component.ts?:42:18)
    at AppointmentsComponent.gotoToday (webpack:///./src/app/components/appointments/appointments.component.ts?:111:18)
    at AppointmentsComponent.ngOnInit (webpack:///./src/app/components/appointments/appointments.component.ts?:64:14)
    at checkAndUpdateDirectiveInline (webpack:///./node_modules/@angular/core/esm5/core.js?:12585:19)
    at checkAndUpdateNodeInline (webpack:///./node_modules/@angular/core/esm5/core.js?:14109:20)

Unit Test:

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppointmentsComponent
      ],
      imports: [
        InfiniteScrollModule,
        FormsModule,
        BrowserAnimationsModule
      ],
      providers: [
        { provide: WebApiService, useClass: MockWebApiService }
      ]
    }).compileComponents();

  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppointmentsComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

/* ...Code missing for brevity... */

class MockWebApiService {
  getAppointments(): Observable<Appointment[]> { return of([]);}
}

Upvotes: 1

Views: 2520

Answers (1)

Tomasz Kula
Tomasz Kula

Reputation: 16837

Given that the test throws on the first test case, your code sample must be either in constructor or ngOnInit. If it's in the constructor please move it to ngOnInit as it will make testing much easier.

It's throwing because switchMap expects this.loadAppointments() to return an observable, but it doesn't. You need to mock this method in order to test your componenent.

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

  component.loadAppointments = () => of([]);

  fixture.detectChanges();
});

This simple change should stop the test from failing so early. You can also consider spying on the loadAppointment method with jasmine.spy, but it really depends on what you are testing for.

Upvotes: 1

Related Questions