我目前在为 NgRx 效果编写单元测试方面遇到了一些困难。
这是我的效果:
navigateToProjectOnInvokeJoinProject$ = createEffect(
() =>
this.actions$.pipe(
ofType(invokeJoinProjectSuccess),
// On reload, projectId is already available. In that case, don't navigate again
concatLatestFrom(() => this.store.select(selectProjectIdFromRoute)),
filter(([_, projectId]) => !projectId),
map(([action, _]) => this.projectDetailsService.initialNavigateToProject(action.projectId))
),
{ dispatch: false }
);
这是测试:
it("should call initialNavigateToProject if project is not opened yet", () => {
const action = invokeJoinProjectSuccess({ projectId, activeUsers: [] });
jest.spyOn(projectDetailsService, "initialNavigateToProject");
actions$ = of(action);
effects.navigateToProjectOnInvokeJoinProject$.subscribe(() => {
expect(projectDetailsService.initialNavigateToProject).toHaveBeenCalledTimes(1);
expect(projectDetailsService.initialNavigateToProject).toHaveBeenCalledWith(projectId);
});
});
它通过了,但只是因为 Expect 语句实际上根本没有被调用。我把
expect(1).toEqual(2)
放在那里以确保测试仍然是绿色的,这当然是不可能的。
为了模拟
ProjectDetailsService
,我使用 MockProvider
库的 ng-mocks
,然后使用 projectDetailsService = TestBed.inject(ProjectDetailsService);
设置 TestBed
我在这里缺少什么?
我试图监视在效果中调用的服务方法,并期望它被触发,但显然它没有被触发。或者更确切地说,甚至没有输入订阅块。
我预计这是因为
concatLatestFrom
和 filter
。我想他们返回一个虚假值,这会停止流。
要解决此问题,您可以使用初始值设置商店,以便它继续。
看一下
done
回调,以便此测试在当前状态下失败。 https://jestjs.io/docs/asynchronous#callbacks
或者,我更喜欢创建一个包含操作的数组,并将该数组用于我的期望语句,例如,请参阅https://timdeschryver.dev/blog/testing-an-ngrx-project#e1aedff7251a2ccd78cb118e42f7f2e2