Search code examples
rxjsjasmine-marblesrxjs-marbles

RxJS testing: marble test confusing case


I'm adding unit testing to my angular/rxjs project, and I'm using the marble test solution. And since I'm using the newer version of rxjs, so I used the build-in "TestScheduler" module.

I'm following this post: https://brianflove.com/2018/06/28/ngrx-testing-effects/, And it gave an example as following:

export class UserEffects {
  @Effect()
  addUser: Observable<Action> = this.actions$
    .ofType<AddUser>(UserActionTypes.AddUser)
    .pipe(
      map(action => action.payload),
      exhaustMap(payload => this.userService.addUser(payload.user)),
      map(user => new AddUserSuccess({ user })),
      catchError(error => of(new AddUserFail({ error })))
    );

  constructor(private actions$: Actions, private userService: UserService) {}

}

and the unit test is below:

describe('addUser', () => {
    it('should return an AddUserSuccess action, with the user, on success', () => {
    const user = generateUser();
    const action = new AddUser({ user });
    const outcome = new AddUserSuccess({ user });

    actions.stream = hot('-a', { a: action });
    const response = cold('-a|', { a: user });
    const expected = cold('--b', { b: outcome });
    userService.addUser = jest.fn(() => response);

    expect(effects.addUser).toBeObservable(expected);
  });
});

I can understand the logic(marble string) here expect one confusing point:

cold('--b', { b: outcome })

why not --b|? Since the response observable has a completion event | in cold('-a|', { a: user });.

Btw, in this post, it will third-party library, but I use native TestScheduler and have the same result.


Solution

  • I want to preface this by saying I'm not too familiar with ngrx, so this is just me guessing: It looks like everything is being passed into an action reducer. The action stream -a is being tested with --b, and you don't want your action reducer to end because you want it to be able to take in the next action.