I have a situation where a component is fetching data from an API, but the data is only needed once, so I have opted not to use a reducer and selector for it. Instead, I am using actions and effects to handle the API call.
Here is the code I am trying to test:
private loadData() {
const subscriptions: Subscription = new Subscription();
subscriptions.add(
this.actions$
.pipe(ofType(EApiActions.ApiLoaded))
.subscribe((action: ApiLoaded) => {
subscriptions.unsubscribe();
this.data = action.result;
})
);
subscriptions.add(
this.actions$
.pipe(ofType(EApiActions.ApiFailure))
.subscribe((action: ApiFailure) => {
subscriptions.unsubscribe();
})
);
this.store.dispatch(
new ApiRequest()
);
}
My test script is as follows:
let mockStore: MockStore;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent],
providers: [
provideMockActions(() => actions$),
provideMockStore({ initialState })
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
mockStore = TestBed.inject(MockStore);
});
it('should dispatch action and trigger the result|failure action handler', () => {
// Arrange
const expectedAction = new ApiRequest();
const dispatchSpy = spyOn(mockStore, 'dispatch');
// Act
fixture.detectChanges();
// Assert
expect(dispatchSpy).toHaveBeenCalledWith(expectedAction);
// Act - test success
mockStore.dispatch(new ApiLoaded([]));
fixture.detectChanges();
// Assert
expect(component.data).not.toBeNull();
});
The test fails after the line expect(dispatchSpy).toHaveBeenCalledWith(expectedAction);
Upon examining the code, it seems that the component is listening for EApiActions.ApiLoaded, so I attempt to dispatch the action with mockStore.dispatch(new ApiLoaded([])); however, the code within my component does not get executed.
How can I solve this issue? Do you believe this approach of using actions and effects is appropriate, or do you think it might be better to go through a reducer to store the result and then access it using a selector?