小编Rob*_*Lee的帖子

Jasmine HTTP 测试未覆盖 RXJS 管道

问题

大家好,我正在向我的 Angular 2 项目添加一些 Karma-Jasmine 单元测试,但我一生都无法在我的服务方法中覆盖 RXJS 操作员。

测试使用 HttpClientTestingModule 和 HttpTestingController。

代码

这是一个仅使用地图运算符的简单示例。

我的服务:

getAssetCount(): Observable<AssetModel[]> {
  return this.http
    .get('/myproject/v1/asset-count')
    .pipe(map(response => response as AssetModel[]));
}
Run Code Online (Sandbox Code Playgroud)

我的服务规范:

service = testBed.get(MyService);
httpMock = testBed.get(HttpTestingController);
...

it('should getAssetCount', () => {
  const dummyResponse = [{...}];
  service.getAssetCount().subscribe((response: AssetModel[]) => {
    expect(response).toEqual(dummyResponse);
    const req = httpMock.expectOne(
      '/myproject/v1/asset-count'
    );
    expect(req.request.method).toBe('GET');
    req.flush(dummyResponse);
    httpMock.verify();
  });
});
Run Code Online (Sandbox Code Playgroud)

结果

由此产生的覆盖范围:

由此产生的覆盖范围

我本以为在测试中订阅可观察对象会触发map()调用,但也许我误解了这些模拟服务的工作原理。

环顾四周,似乎切换到XHRBackend而不是 HttpClientTestingModule 来生成虚拟 200/404/etc 响应可以解决该问题,但除了更多样板之外,似乎大多数人都建议使用 TestingModule。

unit-testing http jasmine rxjs angular

6
推荐指数
1
解决办法
1498
查看次数

如何使用 RXJS 取消内部 HTTP observable 中的待处理请求?

更改页面时取消挂起的 HTTP 请求

我们有一个 Angular 服务,它有一个昂贵的 HTTP 查询,可供 3 个不同的消费者访问。每个消费者都可以随时修改此查询,发出新请求,并且所有其他消费者都必须使用新数据进行更新。

因为 HTTP 订阅在完成后立即关闭,所以我们使用带有行为主体的内部可观察模式来保持消费者的连接(见下文)。

那么问题是,当用户更改页面时,当前挂起的 HTTP 响应无法取消。

通常,我认为在后台丢弃 HTTP 请求不会有太大问题……但除了这是一项昂贵的操作之外,我发现在用户返回后是否确实解决了挂起的响应到页面,它将使用旧查询的数据更新消费者。

没有布埃诺。

服务电话

private dataSubject = new BehaviorSubject<MyData>(...);
public data$ = this.dataSubject.asObservable();
...

getData(): Observable<MyData> {
  if (this.dataSubject)
    return this.data$;
  } else {
    const http$ = this.http.post(...))
      .pipe(map(response => response as MyData),
        takeUntil(this.unsubscribe$)); // see tearDown() below
    http$.subscribe(
      (availableDevices: MyData) => {
        this.dataSubject.next(availableDevices);
      }
    );
    return this.data$;
  }
}
Run Code Online (Sandbox Code Playgroud)

我试图在每个消费者在 ngDestroy() 期间调用的服务中创建一个拆卸方法,但除非我完成了流,否则它不起作用。但那时,当用户返回页面时,我无法再次重新启动流。

tearDown(): void {
  this.unsubscribe$.next();
  this.unsubscribe$.complete();
  // this.dataSubject.next(null);
  // this.dataSubject.complete(); -- …
Run Code Online (Sandbox Code Playgroud)

http observable rxjs angular rxjs-pipeable-operators

4
推荐指数
1
解决办法
4615
查看次数