Reputation: 183
I am learning to write unit tests for ngrx8 application using Jest.
I am testing a component that has subscription to a selector in ngOnInit:
ngOnInit(): void {
this.store.pipe(select(someSelector(this.parameter))).subscribe((res:
// some logic here
});
}
In the .spec.ts file I put provideMockStore
in TestBed configuration:
TestBed.configureTestingModule({
// ...
providers: [
provideMockStore({
initialState, // defined somewhere above
selectors: [
{
selector: someSelector('param'),
value: {a: 'b', c: 'd'}
}
]
})
]
// ...
}).compileComponents();;
So I expect that while running this unit test, I should enter the subscription (the "some logic here" section) in the component .ts file and res
will equal {a: 'b', c: 'd'}
.
That doesn't happen, instead mocked selector is ignored and the real one is used.
Things I tried:
store.overrideSelector(someSelector('param'), {a: 'b', c: 'd')
Putting fixture.detectChanges()
, await fixture.whenStable()
, in different places
Now I am out of options, and the NGRX documentation doesn't cover almost anything.
Upvotes: 3
Views: 2585
Reputation: 6821
Mocking the selector doesn't seem to be the best solution. It would be better to mock the store itself.
You can provide the state in :
provideMockStore({ initialState: your_state })
or
mockStore.setState(your_state);
mockStore.setState(...)
allows you to do tests with different value in your store inside your tests.
BUT I suggest you do do the following if you have a complex store:
MockStoreState
.
type RecursivePartial<T> = {
[P in keyof T]?:
T[P] extends (infer U)[] ? RecursivePartial<U>[] :
T[P] extends object ? RecursivePartial<T[P]> :
T[P];
};
export class MockStoreState {
private store_a: RecursivePartial<Store_A>;
private store_b: RecursivePartial<Store_b>;
build(): any {
const defaultStore_a = {
...
};
const defaultStore_b = {
...
};
return {
store_a: { ...defaultStore_a , ...this.store_a},
store_b: { ...defaultStore_b , ...this.store_b },
};
}
setStore_a(value: RecursivePartial<Store_A>): Store_A_State {
this.store_a= value;
return this;
}
setStore_b(value: RecursivePartial<DatasourceState>): Store_B_State {
this.store_b= value;
return this;
}
}
describe(MyComponent.name, () => {
...
let mockStore: MockStore<any>;
beforeEach(() => {
...
mockStore = TestBed.get(Store);
})
it('...', () => {
const state = new MockStoreState().setStore_a({...})
.build();
mockStore.setState(state);
// HERE you have set the data in your store.
})
}
Upvotes: 3