Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test withLatestFrom in ngrx effects

I have an effect that is taking the latest from params and passing that into an exhaustMap that then calls a service.

@Effect()
loadPlansOnParams$ = this.actions$.pipe(
 ofType(backlogActions.BacklogActionTypes.GET_BOARDS_IN_PARAMS),
 withLatestFrom(this.store.select(fromRoot.getRouterState), (action, router) => {
   const {
     state: {
       queryParams: { boards },
     },
   } = router;
   return {
     boards,
   };
 }),
 exhaustMap(payload => {
   return this.boardService.getBoardsFromParams(payload.boards).pipe(
     map((res: SignalRResult) => {
       const board = res.item;
       return new backlogActions.GetBoardsSuccess(board);
     }),
     catchError(err => of(new backlogActions.GetBoardsError(err))),
   );
 }),
);

Everything is cool. However I cannot get this to test for the life of me. And just about every example I can find is useless.

Here is My test...

describe('getting boards from the params', () => {
    it('should return an empty array if no params', () => {
      const params = { state: { queryParams: {} } };
      const successfulSignalRResult = { isSuccessful: true, item: [] };
      const action = new backlogActions.GetBoardsInParams();
      const outcome = new backlogActions.GetAvailableBoardsSuccess([]);
      actions.stream = hot('-a', { a: action });
      store.select = jest.fn(() => of(params));
      expected = cold('--b', { b: outcome });
      boardSvc.getBoardsFromParams = jest.fn(() => successfulSignalRResult);
      expect(effects.loadPlansOnParams$).toBeObservable({});
    });
  });

No matter what I do with the store.select mock I get back "You provided 'undefined' where a stream was expected."

Any help is appreciated. I'm really hoping that I'm missing something on marbles.

like image 672
s.Lawrenz Avatar asked Oct 19 '25 12:10

s.Lawrenz


2 Answers

I've encountered the same issue and for me the fix was to provide a mock for selectors that are inside the withLatestFrom operator. like this :

provideMockStore({
      initialState: fromStore.initialState,
      selectors: [
        {
          selector: fromStore.getCriteriaList,
          value: {
            industries: '',
            keyword: '',
            tags: ''
          }
        }
      ]
    }),
like image 182
khalil.khaled Avatar answered Oct 21 '25 02:10

khalil.khaled


Maybe, this is late answer. I have encountered same problem.

I don't know the exact reason. In my thought, getRouterState is not initialized when MockStore and effect are used at the same time. When loadPlansOnParams$ is initialized in constructor, getRouterState is not properly initialized.

Simply speaking, initialization for getRouterState is located before loadPlansOnParams$ like this.

@Effect()

SomeVariableForGetRouterState:Observable<SomeThing> = ..... fromRoot.getRouterState ..... like this.. 

loadPlansOnParams$ = this.actions$.pipe(
ofType(backlogActions.BacklogActionTypes.GET_BOARDS_IN_PARAMS),
withLatestFrom( SomeVariableForGetRouterState, (action, router) => {
.....
);
like image 39
Sang B. Han Avatar answered Oct 21 '25 02:10

Sang B. Han



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!