I have a simple user list page and the NgRx actions, reducers, and effect for it.
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { UserService } from '@core/services';
import { search, searchSuccess, searchFail } from './list.actions';
import { UserListFilter } from './list.filter';
@Injectable()
export class UserListEffects {
constructor(private actions$: Actions, private userService: UserService) {}
search$ = createEffect(() =>
this.actions$.pipe(
ofType(search),
switchMap((params: { options: UserListFilter }) =>
this.userService.getUsers(params.options.showDisabled).pipe(
map((items) => searchSuccess({ items })),
catchError((error) => of(searchFail({ error })))
)
)
)
);
}
Whenever I try to test this effect, the tests works, but I get a bunch (10, to be precise) of repeated errors in the console:
ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.
at createInvalidObservableTypeError (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/util/throwUnobservableError.js:2:12)
at innerFrom (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/observable/innerFrom.js:37:43)
at Observable._subscribe (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/observable/defer.js:5:18)
at Observable._trySubscribe (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/Observable.js:37:25)
at cb (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/Observable.js:31:30)
at errorContext (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/util/errorContext.js:19:9)
at Observable.subscribe (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/Observable.js:22:21)
at Actions._subscribe (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/Observable.js:64:75)
at cb (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/Observable.js:29:30)
at errorContext (_karma_webpack_/webpack:/node_modules/rxjs/dist/esm/internal/util/errorContext.js:19:9)
The error happens when I try to inject the effect with TestBed.inject(UserListEffect):
import { Observable, of, throwError } from 'rxjs';
import { TestBed } from '@angular/core/testing';
import { Action, StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { provideMockActions } from '@ngrx/effects/testing';
import { User } from '@core/models';
import { UserListEffects } from './list.effects';
import { UserService } from '@core/services';
import { search, searchSuccess, searchFail } from './list.actions';
class UserServiceMock {
_response: Observable<any> = of([]);
getUsers() {
return this._response;
}
}
fdescribe('User List • Effects', () => {
let effects: UserListEffects;
let actions$: Observable<Action>;
let userService: UserServiceMock;
beforeEach(() => {
userService = new UserServiceMock();
TestBed.configureTestingModule({
imports: [StoreModule.forRoot([]), EffectsModule.forRoot([]), EffectsModule.forFeature([UserListEffects])],
providers: [provideMockActions(() => actions$)],
}).overrideProvider(UserService, { useValue: userService });
//HERE
effects = TestBed.inject(UserListEffects);
});
describe('Given search', () => {
beforeEach(() => {
actions$ = of(
search({
options: {
showDisabled: true
},
})
);
});
it('when success, then return list of users', (done) => {
const items = [{ id: 1 }] as User[];
userService._response = of(items);
effects.search$.subscribe((newAction) => {
expect(newAction).toEqual(searchSuccess({ items }));
done();
});
});
it('when fails, then return the error', (done) => {
const error = 'error';
userService._response = throwError(() => error);
effects.search$.subscribe((newAction) => {
expect(newAction).toEqual(searchFail({ error }));
done();
});
});
});
});
I'm on Angular 14.2 and on NgRx 14.3.1. What's going on with my tests?
I guess that it's something with a pipe or switchmap, but it doesn't make sense that it's throwing 10 error messages when injecting the effect.