Wednesday, May 22, 2019

Mock the NgRx store when testing an Angular 7 application!

How may we handle a component constructor like this at tests?

constructor(public store: Store<IMainStore>) {

 
 

As suggested here we need to mock the store. Make a class like so for that:

import { Injectable } from '@angular/core';
import { Action } from '@ngrx/store';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable()
export class MockStore<T> {
   private state: {
      [selector: string]: BehaviorSubject<any>;
   } = {};
   dispatch: (action: Action) => void = this.emptyPlaceholder;
   emptyPlaceholder():void {};
   setSelectorResult<V>(selector: (state: any) => V, data: V) {
      if (!this.state[<any>selector]) {
         this.state[<any>selector] = new BehaviorSubject(data);
      } else {
         this.state[<any>selector].next(data);
      }
   }
   select(selector: any): Observable<keyof T> {
      if (!this.state[selector]) {
         this.state[selector] = new BehaviorSubject(undefined);
      }
      return this.state[selector];
   }
}

 
 

Use the class like this:

import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import { OuterWrapperComponent } from './components/outer-wrapper.component';
import { MenuWrapperComponent } from './components/menu-wapper/
      menu-wrapper.component';
import { ActiveDirectoryContract } from './contracts/active-directory.contract';
import { ActiveDirectoryContractStub } from './contracts/active-directory.contract.stub';
import { MockStore } from './testing/mock-store';
import { IMainStore } from './state-management/store/store';
import { Store } from '@ngrx/store';
describe('AppComponent', () => {
   let mockStore: MockStore<IMainStore>;
   beforeEach(async(() => {
      TestBed.configureTestingModule({
         imports: [
            RouterTestingModule
         ],
         declarations: [
            AppComponent,
            OuterWrapperComponent,
            MenuWrapperComponent
         ],
         providers: [
            {provide: Store, useClass: MockStore},
            {provide: ActiveDirectoryContract, useValue: new ActiveDirectoryContractStub()}
         ]
      }).compileComponents();
      mockStore = TestBed.get(Store);
   }));
   
   it('should create the app', () => {
      const fixture = TestBed.createComponent(AppComponent);
      const app = fixture.debugElement.componentInstance;
      expect(app).toBeTruthy();
   });
   
   it(`should have as title 'Trifecta'`, () => {
      const fixture = TestBed.createComponent(AppComponent);
      const app = fixture.debugElement.componentInstance;
      expect(app.title).toEqual('Trifecta');
   });
   
   it('should render title in a h1 tag', () => {
      const fixture = TestBed.createComponent(AppComponent);
      fixture.detectChanges();
      const compiled = fixture.debugElement.nativeElement;
      expect(compiled.querySelector('img').alt).toContain('Reporting');
   });
});

No comments:

Post a Comment