Using CreateSpyObject with NGRX store testing

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});