In the application, there is a service, which is used in an action that then updates the state.
When running the application everything works fine using a piped observable. However, when creating the test, I am not able to update the state without adding a subscription for it to work.
./MyApiService.ts
@Injectable({ providedIn: 'root' })
export class MyApiService {
constructor(private http: HttpClient) {}
getSomeData(): Observable<any> {
return this.http.get('https://some-url.com/')
}
}
./MyState.ts
@State<StateModel>({})
@Injectable()
export class MyState {
constructor() {
private myApiService: MyApiService,
}
@Action(SomeAction.UpdateData)
updateData(ctx: StateContext<StateModel>) {
return this.myApiService.getSomeData().pipe(
tap(data => {
if (data) {
ctx.patchState({ data });
}
}
)
}
}
Now for the test:
./MyState.spec.ts
desribe('some test', () => {
beforeEach(() => {
stub.MyApiService = {
getSomeData: jest.fn().mockReturnValue(of({ foo: 'bar' }]);
}
stub.ctx = {
patchState: jest.fn(),
}
state = new MyState(stub.MyApiService);
});
it('should update data', () => {
state.updateData(stub.ctx);
expect(stub.MyApiService.getSomeData).toHaveBeenCalledTimes(1); // works
expect(stub.ctx.patchState).toHaveBeenCalledTimes(1); // fails!
});
});
That does not work.
However, if I change the action to have a subscription...
./MyState.ts
@State<StateModel>()
@Injectable()
export class MyState {
constructor() {
private myApiService: MyApiService,
}
@Action(SomeAction.UpdateData)
updateData(ctx: StateContext<StateModel>) {
return this.myApiService.getSomeData().pipe(
tap(data => {
if (data) {
ctx.patchState({ data });
}
}
).subscribe(); // added here and now the test succeeds
}
}
...it works. But it feels a bit off to have to subscribe and also have to unsubscribe when that is not necessary with just the pipe.
CodePudding user response:
what Matthieu explained is correct. If you dont subscribe to an async-call nothing will ever happend. the pipe() operator is only there to cut into the stream and change the data before it reaches the component/services. But without the Subscription the pipe() will never trigger.
Which means in your Tests, that you have to subscribe to get the data, just like in a normal component.