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?
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.