angularngrxjasmine-marbles

Unexpected errors testing the ngrx mock store


I think I found a solution, go to the end of the question

I have a simple test with jasmine-marbles and I am getting this error and I do not know what is happening. Any ideas?

Expected $[0].notification.kind = 'E' to equal 'N'.

Expected $[0].notification.value = undefined to equal [ ].

Expected $[0].notification.error = TypeError: Cannot read property 'pools' of undefined to equal undefined.

Expected $[0].notification.hasValue = false to equal true.

pool-management.component.ts

    @Component({
  selector: 'app-pool-list',
  templateUrl: './pool-list.component.html',
  styleUrls: ['./pool-list.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class PoolListComponent implements OnInit {

  pools$ = this.store.pipe(select(selectPools));

  constructor(private store: Store<fromPoolManagement.State>) { }

  addPool(): void {
    this.store.dispatch(PoolManagementActions.addPool({lot: 'XXX', user: 'XYZ', cutDate: new Date().toISOString()}));
  }

  ngOnInit(): void {
    this.store.dispatch(PoolManagementActions.getPools());
  }

}

pool-management.selectors.ts

export const poolManagementSelector = createFeatureSelector('poolManagement');

export const selectPools = createSelector(
  poolManagementSelector,
  (state: State) => state.pools
);

pool-list.component.spec.ts

fdescribe('PoolListComponent', () => {
    let component: PoolListComponent;
    let fixture: ComponentFixture<PoolListComponent>;
    let mockStore: MockStore<fromPoolManagement.State>;

    beforeEach(() => {
      const initialState = { pools: [] } as fromPoolManagement.State;
      TestBed.configureTestingModule({
        declarations: [PoolListComponent],
        providers: [provideMockStore({ initialState })],
      })
        .compileComponents();
      fixture = TestBed.createComponent(PoolListComponent);
      component = fixture.componentInstance;
      mockStore = TestBed.get(Store);
      fixture.detectChanges();
    });

    it('should create', () => {
      expect(component).toBeTruthy();
    });

    it('should work, but this test is not working', () => {
      const expected = cold('a', { a: []});
      expect(component.pools$).toBeObservable(expected);
    });

    afterEach(() => {
      fixture.destroy();
    });

  });

console.log('expected', expected);

enter image description here


Solution

  • Since my app.module has a

    StoreModule.forRoot([]),

    and I was trying to test a lazy loaded module with a .forFeature:

    StoreModule.forFeature('poolManagement', poolManagementReducer),

    I was having some errors of undefined because my selector was unable to find the poolManagement piece of the store.

    I have solved it providing the MockStore with a mock state:

    interface MockState {
        poolManagement: {
          pools: Array<Pool>
        };
      }
    let mockStore: MockStore<MockState>;
    

    And setting the initial state acording the MockState:

    const initialState = { poolManagement: { pools: [] } };
    

    That's all. If anyone has a better solution please let me know.