You provided 'undefined' where a stream was expected whenever injecting effects in test

Viewed 25

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.

0 Answers
Related