Ngrx testing - How to configure TestBed to instantiate the entire state store in a test

I want to run some integration tests for the ngrx 4 state repository in an Angular 5 application. My desire is to test ngrx actions, effects, webapi, server layout and selectors in one shot. Writing separate tests for effects and gears will be sink time, and I need to cut some angles. I only need to know when one of my pages fails in the wrong place.

I managed to do this in a previous project, using along with a redux along with Angular 2. It was quite easy to configure. However, with ngrx I have some problems. Somehow it is AccountsWebapinot entered correctly into the class AccountsEffectsat startup TestBed. Instead of getting a webapi instance, it looks like I'm getting a constructor. At the same time, the same webapi seems to be entered and created correctly in _AccountsService.

accounts.service.spec.ts

describe("AccountsService - ", () => {

    let accService: AccountsService;

    beforeAll( ()=> {
        TestBed.resetTestEnvironment();
        TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
    });

    beforeEach(async(() => {

        TestBed.configureTestingModule({
            imports: [
                StoreModule.forRoot({appReducer}),
                EffectsModule.forRoot([AccountsEffects]),
            ],
            declarations: [],
            providers: [
                { provide: AccountsService, useValue: AccountsService },
                { provide: AccountsWebapi, useValue: AccountsWebapi },
                // ... Other dependencies
            ]
        }).compileComponents();

        // Instantiation
        let _AccountsUtilsService = TestBed.get(AccountsUtilsService);
        let _store = TestBed.get(Store);
        let _AccountsService = TestBed.get(AccountsService);
        // ... Other dependencies

        accService = new _AccountsService(
            new _AccountsUtilsService(),
            new _AccountsWebapi(), 
            _store,
            // ... Other dependencies
        );

    }));

    it("Sample Test", () => {
        console.log(`Accounts SERVICE`, accService.accountsWebapi);
        accService.getAccountAsync(1);
        expect(1).toEqual(1);
    });

accounts.effects.ts

@Injectable()
export class AccountsEffects {

    constructor(
        private actions$: Actions,
        private store$: Store<AppState>,
        private accountsService: AccountsService,
        private accountsWebapi: AccountsWebapi,
    ) {
        console.log('Accounts EFFECTS', this.accountsWebapi)

        // Typing this line will instantiate the dependency...
        this.accountsWebapi = new (this.accountsWebapi as any)()
    }

Console log

enter image description here

0
source share
1 answer

Finally, I found a way to run this test. I am 100% sure that there is a much better way to do this. Until I find it, it should do.

/** Force initialise the web api in effects */
@Injectable()
class AccountsEffectsTest extends AccountsEffects {

    constructor(
        protected _actions$: Actions,
        protected _store$: Store<AppState>,
        protected _accountsWebapi: AccountsWebapi,
    ) {
        super(
            _actions$,
            _store$,
            _accountsWebapi,
        );

        // This line looks ugly but it spares a lot of imports
        // Certainly there is a better way then this
        let providers = ((new HttpModule()) as any).__proto__.constructor.decorators['0'].args['0'].providers;
        let injector = ReflectiveInjector.resolveAndCreate([
            ...providers
        ]);

        this.accountsWebapi = new (_accountsWebapi as any)(
            null,
            injector.get(Http)
        );

        console.log('Accounts EFFECTS', this.accountsWebapi);
    }

}

, webapi , . , , webapi. , . , . - , , , .

0

Source: https://habr.com/ru/post/1662236/


All Articles