递归RxJS方法中Post调用未触发的Jest测试问题
问题描述
我在服务中实现了一个递归发送POST请求的方法,使用RxJS的map操作符链式调用请求,代码如下:
bulkPostRecursive(offset: number, limit: number, ids: string[]): Observable<void> { const filteredIds: string[] = ids.slice(offset, offset + limit); const end: number = ids.length; const data: Record<string, string[]> = { ids: filteredIds, }; if (offset + limit < end) { return this.bulkPostRecursive(offset + limit, limit, ids).pipe( map((): void => { this.apiCallService.post('/api_url', data); // 这部分逻辑本身正常 }), ); } else { return this.apiCallService.post('/api_url', data); // 这部分逻辑本身正常 } } bulkPost(ids: string[]): Observable<void> { const offset: number = 0; const limit: number = 2; // 测试用的限制值 return this.bulkPostRecursive(offset, limit, ids); }
为测试包含this.bulkPostRecursive(offset + limit, limit, idList).pipe的分支,我编写了如下测试用例:
it('bulkPostRecursive(): should call bulkPostRecursive', () => { const bulkPostRecursiveSpy = jest.spyOn(service, 'bulkPostRecursive'); apiCallService.post.mockReturnValue(of({'somevalue': 'somevalue'})); service.bulkPostRecursive(0, 4, ['id','id','id','id']); expect(bulkPostRecursiveSpy).toHaveBeenCalled(); expect(apiCallService.post).toHaveBeenCalled(); // 此处报错 });
测试时出现错误:
expect(jest.fn()).toHaveBeenCalled() Expected number of calls: >= 1 Received number of calls: 0
apiCallService.post未被调用,求指导如何正确触达该分支。
解决方法
1. 订阅Observable触发异步逻辑
RxJS的Observable是冷Observable,只有被订阅时才会执行内部逻辑。你的测试仅调用了bulkPostRecursive但未订阅返回的Observable,导致所有异步逻辑未触发。
修改测试代码,添加订阅并处理异步完成:
it('bulkPostRecursive(): should call bulkPostRecursive and apiCallService.post', (done) => { const bulkPostRecursiveSpy = jest.spyOn(service, 'bulkPostRecursive'); apiCallService.post.mockReturnValue(of({'somevalue': 'somevalue'})); // 订阅Observable,触发所有递归和请求逻辑 service.bulkPostRecursive(0, 4, ['id','id','id','id']).subscribe({ complete: () => { expect(bulkPostRecursiveSpy).toHaveBeenCalled(); expect(apiCallService.post).toHaveBeenCalled(); done(); // 通知Jest异步测试完成 } }); });
2. 修复递归逻辑的Observable链式问题
当前递归分支中,map操作符内调用this.apiCallService.post但未返回该Observable,会导致:
- POST请求的错误无法被上层Observable捕获
- 请求执行顺序不受控
建议用concatMap(保证请求顺序)替换map,并返回POST请求的Observable:
if (offset + limit < end) { return this.bulkPostRecursive(offset + limit, limit, ids).pipe( concatMap(() => { return this.apiCallService.post('/api_url', data); // 返回Observable串联逻辑 }), ); }
3. 修正测试用例的参数错误
你的测试用例中ids数组存在语法错误:['id','id','id,'id']缺少一个引号,正确写法应为['id','id','id','id'],否则会导致数组长度不符合测试预期。
内容的提问来源于stack exchange,提问作者Aastha B
相关产品推荐
相关产品推荐

