Search code examples
angularunit-testingjasmineangular6ngrx

How can an ngrx feature selector be unit tested in Jasmine with Angular 6?


I have a feature selector and adjacent selectors for my products feature:

const getProductState = createFeatureSelector<fromProducts.State>('products');

export const getOldProducts = createSelector(
    getProductState,
    state => state.oldProducts
);

export getNewProducts = createSelector(
    getProductState,
    state => state.newProducts
);

I want to unit test against these selectors. Most articles and posts I read only deal with non-feature selectors, so come time to mock the feature state, my tests are returning undefined for the state object. My spec file looks like this:

beforeEach(async(() => {
    TestBed.configureTestingModule({
        imports: [
            StoreModule.forRoot({}),
            StoreModule.forFeature('products', fromProduct.reducer)
        ],
        declarations: [],
        providers: [{
            provide: Store, useClass: class { select = jasmine.createSpy('select'); dispatch = jasmine.createSpy('dispatch'); }
        }]
    })
    mockStore = TestBed.get(Store);
}));

it('getOldProducts should return the oldProducts', () => {
    const state = {
        name: 'Product1',
        oldProduct: {
            price: 45.00
        },
        newProduct: {
            price: 50.00
        }
    }: fromProduct.State;
    expect(selectors.getOldProducts(state.oldProducts)).toBe(state.oldProducts);
});

Error keeps saying Cannot read property 'oldProducts' of undefined, which leads me to believe the getProductState feature selector isn't being mocked properly.

Thanks!


Solution

  • I had the same problem and this thread helped me. Although the solution is not clear.

    You need to use the projector function from the selector as @J-man said. For your case would be:

    expect(selectors.getOldProducts.projector(state.oldProducts)).toBe(state.oldProducts);