angulartypescriptrxjs

Why does instanceof Observable return false in my tests?


I have a simple screen with a MatTable that uses an Observable as its data source. The data source is returned from an API service that fetches it via HTTP. (Listener is a plain value object.)

@Injectable()
export class ApiService {
  getListeners(): Observable<Listener[]> {
    return this.http.get<Listener[]>(this.listenersEndpoint, {headers}).pipe(
      tap(listeners => console.log("fetched Listeners")),
      catchError(this.handleError('getListeners', []))
    );
  }
}

@Component(
  template: `
    <table mat-table [dataSource]="listeners$"><!-- column definitions --></table>`
)
export class ListenersTableComponent implements OnInit {
  listeners$: Observable<Listener[]>;

  constructor(private api: ApiService) {}

  ngOnInit() {
    this.listeners$ = this.api.getListeners().pipe(
      tap({complete: () => console.log("loaded")})
    );
  }
}

This works fine in production. For testing, I use a mock API service that returns an Observable of an array of Listeners.

  const apiService = {
    getListeners: () => {
      const list = [new Listener(), new Listener()];
      return of(list);
    }
  } as ApiService;

All the tests that use this mock fail with the message "Error: Provided data source did not match an array, Observable, or DataSource", which originates in @angular/cdk/esm2015/table.js. The code that fails in tests is:

   else if (this.dataSource instanceof Observable) {
       dataStream = this.dataSource;
   }

When I examine this.dataSource in the debugger, it's an Observable in both cases. The only real difference is that the value in test is an array, while in production it seems to be another Observable.

Can anyone tell me why the test version fails?


Solution

  • I've faced this problem before and it's really hard to debug. The cause of the problem is, that there are two (or more) rxjs Observable class definitions in your project.

    You can try these steps:

    1) Make sure you only import Observable from rxjs, not rxjs/Observable.

    2) Try to remove rxjs/compat if you're still using it.

    3) Make sure the problem is not caused by any test config (tsconfig, karma.conf.js)

    4) Make sure you only have one version of rxjs installed.