Search code examples
angularjstestingkarma-runnerngrx

Testing with Karma Angular NgRX effects with applied timer


Having the following NgRX effect

loadData$: Observable<any> = createEffect((): Observable<Action> => {
        return this.actions$.pipe(
            ofType(loadDataStarted),
            switchMap(() => {
                return timer(0, 10000).pipe(
                    switchMap(() => this.dataService.loadNewData().pipe(
           
                    )),
                );
            }),
        );
    });

after all the requirements are mocked try to test if dataService.loadNewData() is getting called, but the test will fail

beforeEach(() => {
     service.loadNewData.and.returnValue(of(data));
});

it('should call service', fakeAsync(() => {
    tick(10000)
    expect(service.loadNewData).toHaveBeenCalledOnceWith();
}));

How do I mock correctly this case


Solution

  • It seems you perform the subscription to the effect outside of the actual test (the it block). This means the subscription lives outside of the fakeAsync timer and because of this, the tick(..) has no effect.

    To solve this, make sure to setup everything inside your fakeAsync test block.

    A general recommendation would be to use marble testing for this: https://ngrx.io/guide/effects/testing#marble-diagrams

    Edit: A concrete solution is found in https://stackoverflow.com/a/65857864/2544163