如何在服务调用中对 mergeMap 进行单元测试

How to unit test mergeMap in service call

我想对包含使用 mergeMap 调用两个 API 的方法的服务进行单元测试。 我已经编写了测试用例,但它只通过了第一个 API 调用。我无法弄清楚这如何适用于 API 调用。

这是我的 posts.service.ts:

getRequest():Observable<any>{
   return this.httpClient.get<any>(`https://some-api/v1/get`).pipe(
      mergeMap(token=>this.httpClient.get<optout>(`https://another-api/v2/get`))
    )
  }

这是我试过的 posts.service.spec.ts 文件:


describe('PostsService', () => {

  let service: postsService;
  let httpController: HttpTestingController;
  let apiURL=environment.apiURL;

  let getTokenApi='http://https://some-api/v1/get';
  let getProductApi='https://another-api/v2/get';

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports:[HttpClientTestingModule,HttpClientModule],
      providers:[{provide:API_CONFIG_TOKEN,useValue:{usewsfApi:false}},postsService]
    });
    service = TestBed.get(postsService);
    httpController=TestBed.get(HttpTestingController);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('should retrieve the products and token from API via GET', () => {
    const postsMock:optout={   
        "productsample": [     
          {     
            "privacyType": "val1",     
            "consented": false,    
          },{     
            "privacyType": "val2",     
            "consented": false,     
          },{  
            "privacyType": "val3",  
            "consented": true,
          }
        ]
    }

    service.getRequest().subscribe(posts=>{
      expect(posts).toEqual(postsMock);
    })

    const req=httpController.expectOne({
      method:'GET',
      url:getTokenApi
    });
  
    req.flush(postsMock);
  });
});

在继续测试 mergeMap 内的调用之前,您需要修复以下导致单元测试 运行 错误的代码:

it('should retrieve the products and token from API via GET', () => { 同步测试 运行,但是以下 expect 调用是 运行 异步:

service.getRequest().subscribe(posts=>{
  expect(posts).toEqual(postsMock);
})

这意味着单元测试不会等待异步代码完成 运行ning 并断定测试已经完成,而没有给这些 expect 调用机会 运行 .此外,他们有可能永远不会 运行 开头。

我建议将单元测试参数更改为 (done) => {,然后在 expect 之后添加 done 回调,如下所示:

service.getRequest().subscribe(posts=>{
  expect(posts).toEqual(postsMock);
  done();
})

完成上述操作后,您需要做的就是使用适当的 return 货物重复 getProductApi 调用的 flush 实现。

这应该会调用 service.getRequest().subscribe( 调用,您应该能够断言结果。但是,我可以看到您当前期望的结果是 postsMock,考虑到您正在测试的实际代码是不正确的,因为它应该是 mergeMap.

的结果

希望这能引导您走向正确的道路!