Angad
Angad

Reputation: 1124

how to test ngrx/effects class in angular2?

i have a ngrx/effects class below. I want to test it but when I run my test, it is not printing anything but still passes. the test should be when I trigger an action TRIGGER_LOAD_NAVIGATION_ITEMS, I should get mocked resultset and returned action type as LOAD_NAVIGATIONS_LINKS

EFFECTS file

import { Injectable } from '@angular/core';
import { Effect, Actions } from '@ngrx/effects';
import { NavigationActionType } from 'app/core/store/actions/navigation/navigation.action';
import { NavigationService } from 'app/core/services/navigation.service';
import 'rxjs/add/operator/switchMap';

@Injectable()
export class NavigationServiceEffect {
    @Effect()
    navigations$ = this.actions$
                        .ofType(NavigationActionType.TRIGGER_LOAD_NAVIGATION_ITEMS)
                        .switchMap( () => this.navigationService.load())
                        .map(data => ({ type: NavigationActionType.LOAD_NAVIGATIONS_LINKS, payload: data}));

    constructor(private actions$: Actions, private navigationService: NavigationService) {}
}

Test File

import { Http, Request, RequestOptionsArgs } from "@angular/http";
import { RouterModule, Router } from "@angular/router";


class HttpMock extends Http {

    get(url: string, options?: RequestOptionsArgs): any {

    }

    request(url: string | Request, options?: RequestOptionsArgs): any {

    }
}

fdescribe('Tag Effect', () => {
    let runner: EffectsRunner;
    let navEffects: NavigationServiceEffect;
    let navService: NavigationService;
    let actions: Actions;

    beforeEach(() => TestBed.configureTestingModule({
        imports: [
            EffectsTestingModule,
            RouterModule,
            StoreModule.provideStore(reducers())
        ],
        providers: [
            Actions,
            NavigationService,
            HttpService,
            { provide: Http, useClass: HttpMock },
            { provide: Router, useClass: class { navigate = jasmine.createSpy("navigate"); } }
        ]
    }));

    it('Call Load Navigation items action after Trigger Load aciton',
        inject([
            Actions, NavigationService
        ],
            ( _actions, _navService) => {
                actions = _actions;
                navService = _navService;

                spyOn(navService, 'load')
                    .and.returnValue(Observable.of([
                        { "name": "Help", "hasChild": false, "roles": [101, 151, 201, 301, 401], "url": "help" }
                    ]));


                navEffects = new NavigationServiceEffect(actions, navService);

                navEffects.navigations$.subscribe(r => console.log(r));

                navEffects.navigations$.subscribe(result => {

                    console.log(result);
                    expect(result.type).toEqual(NavigationActionType.LOAD_NAVIGATIONS_LINKS);
                    expect(result.payload.length).toEqual(3); // This should fail

                });
            }));

});

The test should fail as the length of the payload expected is 1 and is equal to 3 in the statement above so it should fail. But the test passes but no console output is logged. How can I test the above file?

Upvotes: 1

Views: 725

Answers (1)

JeB
JeB

Reputation: 12133

Your assertions are defined inside subscribe, which makes your test asynchronous.
In fact, your test is probably finishing before the action result is fired.
To fix this you need to wrap your test with async function like this:

   it('Call Load Navigation items action after Trigger Load aciton', 
      async(
        inject([
            Actions, NavigationService
        ],
            ( _actions, _navService) => {
                actions = _actions;
                navService = _navService;

                spyOn(navService, 'load')
                    .and.returnValue(Observable.of([
                        { "name": "Help", "hasChild": false, "roles": [101, 151, 201, 301, 401], "url": "help" }
                    ]));


                navEffects = new NavigationServiceEffect(actions, navService);

                navEffects.navigations$.subscribe(r => console.log(r));

                navEffects.navigations$.subscribe(result => {

                    console.log(result);
                    expect(result.type).toEqual(NavigationActionType.LOAD_NAVIGATIONS_LINKS);
                    expect(result.payload.length).toEqual(3); // This should fail

                });
            })));  

More about async here.

Upvotes: 1

Related Questions