1. in the whole describe() lambda function, define below handles that can be referenced in all tests.
// use SpyObj because we want to spy multiple methods of the object const testStore = jasmine.createSpyObj('Store', ['select', 'dispatch', 'pipe']); // used to mock receving dispatched action const actions$: ReplaySubject<any> = new ReplaySubject(); let fixture : ComponentFixture<CurrentComponent>; let component: CurrentComponent;
2. both sync and async version of beforeEach happens before It()
beforeEach(async(() => { ...... TestBed.configureTestingModule({ declarations: [XComponent, YComponent, ......], providers: [XService, YService, // normal injection provideMockActions(() => actions$), { provide: Store, useValue: testStore }, ] }) .compileComponents(); //compileComponents is async method })); beforeEach(()=>{ testStore.dispatch.and.returnValue(true); testStore.select.and.callFake(()=>Observable.of(false)); testStore.pipe.and.callFake(()=>Observable.of(true)); // the store just gave some random objects so component won't throw exception fixture = TestBed.createComponent(CurrentComponent); component = fixture.componentInstance; });
3. the tests Itself
It('some test', ()=> { action$.next({type: '[Action Name] Action Description', payload: { success: true} }); // mocking the component getting an action from the store. component.someField = true; // because we called faked "select" and "pipe" spy methods, so we have to manually do the job. fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; expect(compile.querySelector(".elementId")).toBeTruthy(); expect(testStore.dispatch).toHaveBeenCalledWith(new SomeAction(...)); });
the drawback of this method is “component.someField = true;”, this is NOT really testing the NGRX action pipe/select and subscription method content.
to fix that, “testStore.select.and.callFake(()=>Observable.of(false));” need to change to fake something that will really fit and be passed to the subscription method. like
()=>Observable.of({the projection of appState});