Angular 单元测试NgRx效果(调用其他效果),以确保服务方法调用两次
我正在使用ngrx 8.3.0,想测试一下我的特效类。其中一部分是这样的:Angular 单元测试NgRx效果(调用其他效果),以确保服务方法调用两次,angular,unit-testing,jestjs,ngrx,Angular,Unit Testing,Jestjs,Ngrx,我正在使用ngrx 8.3.0,想测试一下我的特效类。其中一部分是这样的: @Effect() onSubmit$ = this.actions.pipe( ofType<RequestSubmission>(SubmissionActionType.REQUEST_SUBMISSION), switchMap(request => { return this.service
@Effect()
onSubmit$ = this.actions.pipe(
ofType<RequestSubmission>(SubmissionActionType.REQUEST_SUBMISSION),
switchMap(request => {
return this.service
.submit(request.content.slice((request.iteration - 1) * 2,request.iteration * 2))
.pipe(map(s => SubmissionAction.submissionAccepted(request.content, s, request.iteration)),
catchError(error => of(SubmissionAction.submissionFailed(error.status)))
);
})
);
@Effect()
submissionAccepted$ = this.actions.pipe(
ofType<SubmissionAccepted>(SubmissionActionType.SUBMISSION_ACCEPTED),
map(request =>
request.iteration * 2 < request.content.length
? SubmissionAction.requestSubmission(request.content, request.iteration + 1)
: SubmissionAction.submissionCompleted()
)
);
不幸的是,间谍检测到该函数只被调用了一次
我还想过在期望函数被调用两次之前独立订阅第二个效果
actions$.next(SubmissionAction.submissionAccepted(content,{result: []}, 1));
await effects.submissionAccepted$.subscribe();
但我得到了同样的结果。有人知道测试中第一个效果的订阅是否应该自动调用第二个效果吗?
提前感谢您抽出时间。在同事的帮助下,我终于能够测试代码了。在测试中,我不再期望服务函数被调用两次,而是遵循完整的效果流
it(`should process effects loop correctly`, (done: DoneCallback) => {
actions$ = new Subject<SubmissionAction>();
const content = ['a80b04a8','155b5a51','a19d0a7a'];
let iteration = 1;
jest.spyOn(service, 'submitReference').mockImplementation(() => {
const status = 'SUBMITTED';
const submissionNumbers = content.slice((iteration - 1) * 2, iteration * 2)
return of(<Submissions>{ submissionNumbers });
});
effects.onSubmit$.subscribe(action => {
expect(action.type).toEqual(SubmissionActionType.SUBMISSION_ACCEPTED);
actions$.next(action);
});
effects.submissioneAccepted$.subscribe(action => {
iteration++;
if (iteration < 3) {
expect(action.type).toEqual(SubmissionActionType.REQUEST_SUBMISSION);
expect((action as RequestSubmission).iteration).toEqual(2);
actions$.next(action);
} else {
expect(action.type).toEqual(SubmissionActionType.SUBMISSION_COMPLETED);
actions$.complete();
done();
}
});
actions$.next(SubmissionAction.requestSubmission(content, iteration));
});
it(`should process effects loop correct`,(完成:DoneCallback)=>{
动作$=新主题();
常量内容=['a80b04a8'、'155b5a51'、'a19d0a7a'];
设迭代=1;
spyOn(服务,'submitReference').mock实现(()=>{
常量状态='已提交';
const submissionNumbers=content.slice((迭代-1)*2,迭代*2)
返回({提交编号});
});
effects.onSubmit$.subscribe(操作=>{
expect(action.type).toEqual(SubmissionActionType.SUBMISSION\u接受);
动作$.next(动作);
});
effects.submissionaccepted$.subscribe(操作=>{
迭代++;
if(迭代<3){
expect(action.type).toEqual(SubmissionActionType.REQUEST\u SUBMISSION);
expect((按请求提交操作).iteration).toEqual(2);
动作$.next(动作);
}否则{
expect(action.type).toEqual(SubmissionActionType.SUBMISSION\u完成);
动作$.complete();
完成();
}
});
actions$.next(SubmissionAction.requestSubmission(内容、迭代));
});
更清楚地说,我们订阅这两种效果(onSubmit和submissioneAccepted),并期望根据循环的迭代调用适当的操作。当循环完成时,订阅和测试也完成了。最后,我们调度第一个操作来触发整个过程在同事的帮助下,我终于能够测试代码了。在测试中,我不再期望服务函数被调用两次,而是遵循完整的效果流
it(`should process effects loop correctly`, (done: DoneCallback) => {
actions$ = new Subject<SubmissionAction>();
const content = ['a80b04a8','155b5a51','a19d0a7a'];
let iteration = 1;
jest.spyOn(service, 'submitReference').mockImplementation(() => {
const status = 'SUBMITTED';
const submissionNumbers = content.slice((iteration - 1) * 2, iteration * 2)
return of(<Submissions>{ submissionNumbers });
});
effects.onSubmit$.subscribe(action => {
expect(action.type).toEqual(SubmissionActionType.SUBMISSION_ACCEPTED);
actions$.next(action);
});
effects.submissioneAccepted$.subscribe(action => {
iteration++;
if (iteration < 3) {
expect(action.type).toEqual(SubmissionActionType.REQUEST_SUBMISSION);
expect((action as RequestSubmission).iteration).toEqual(2);
actions$.next(action);
} else {
expect(action.type).toEqual(SubmissionActionType.SUBMISSION_COMPLETED);
actions$.complete();
done();
}
});
actions$.next(SubmissionAction.requestSubmission(content, iteration));
});
it(`should process effects loop correct`,(完成:DoneCallback)=>{
动作$=新主题();
常量内容=['a80b04a8'、'155b5a51'、'a19d0a7a'];
设迭代=1;
spyOn(服务,'submitReference').mock实现(()=>{
常量状态='已提交';
const submissionNumbers=content.slice((迭代-1)*2,迭代*2)
返回({提交编号});
});
effects.onSubmit$.subscribe(操作=>{
expect(action.type).toEqual(SubmissionActionType.SUBMISSION\u接受);
动作$.next(动作);
});
effects.submissionaccepted$.subscribe(操作=>{
迭代++;
if(迭代<3){
expect(action.type).toEqual(SubmissionActionType.REQUEST\u SUBMISSION);
expect((按请求提交操作).iteration).toEqual(2);
动作$.next(动作);
}否则{
expect(action.type).toEqual(SubmissionActionType.SUBMISSION\u完成);
动作$.complete();
完成();
}
});
actions$.next(SubmissionAction.requestSubmission(内容、迭代));
});
更清楚地说,我们订阅这两种效果(onSubmit和submissioneAccepted),并期望根据循环的迭代调用适当的操作。当循环完成时,订阅和测试也完成了。最后,我们分派第一个动作来触发整个过程看起来第二个效果只是返回动作,但不分派任何动作,所以这可能是问题所在。如果仍然不起作用,创建StackBlitz演示会很有帮助。一个样板项目,你可以开始。非常感谢你的评论。实现工作正常,我已经手动测试了它。我无法让测试通过,因为我不确定是否通过调用第一个操作并订阅第一个效果,所有过程(调用的新效果)都会像在实际代码中一样自动完成。我认为,如果不在测试用例中调度第二个效果的操作,它不会工作。如果我单独分派它们,这有点超出了测试的全部目的,但再次感谢您的Input。我试图测试现有的实现,显然我必须重构实现本身。看起来第二个效果只是返回操作,但不分派任何操作,所以这可能是问题所在。如果仍然不起作用,创建StackBlitz演示会很有帮助。一个样板项目,你可以开始。非常感谢你的评论。实现工作正常,我已经手动测试了它。我无法让测试通过,因为我不确定是否通过调用第一个操作并订阅第一个效果,所有过程(调用的新效果)都会像在实际代码中一样自动完成。我认为,如果不在测试用例中调度第二个效果的操作,如果我单独发送它们,这有点超出了测试的全部目的,但再次感谢您的输入。我正在尝试测试现有的实现,显然我必须重构实现本身。