You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:15:18