首页 > 解决方案 > 角度:从已解决的 Promise 中获取 httpClient.get 测试失败

问题描述

我很难为从已解决的承诺httpClient.get(...)内部调用 angular 的服务编写测试。then在整个应用程序内部(即不是测试),一切都按预期工作,承诺得到解决,并且从已解决的承诺的数据中提取 URL 以进行httpClient.get调用

然而,在测试中,即使承诺已解决(then(...)已执行),httpClient.get(...)也不会明显执行。

为了说明这个问题,我创建了一个基于 Angular 的 Http Guide 测试的片段。在此处查看整个内容:https ://stackblitz.com/edit/angular-y21e6j

带有承诺的测试失败了:

错误:预期有一个对条件“匹配 URL:api/heroes”的匹配请求,但没有找到。

一般来说,我有两个功能:

  getHeroes(): Observable<any> {
    const sub = new Subject();
    this.http.get<any>(this.heroesUrl)
      .pipe(
      catchError(this.handleError('getHeroes', []))
      ).subscribe(data => sub.next(data));
    return sub;
  }


  notWorking(): Observable<any> {
    const sub = new Subject();
    const promise = Promise.resolve([this.heroesUrl]);
    promise.then(url => {
      console.log('Promise is resolved');
      this.http.get<any>(url[0])
        .pipe(
        catchError(this.handleError('getHeroes', []))
        ).subscribe(data => sub.next(data));
    })
    return sub;
  }

我还从角度指南中复制了测试,并为第二种方法插入了一个。它们看起来像这样:

it('should return expected heroes (called once)', () => {

  heroService.getHeroes().subscribe(
    heroes => expect(heroes).toEqual(expectedHeroes, 'should return expected heroes'),
    fail
  );

  // HeroService should have made one request to GET heroes from expected URL
  const req = httpTestingController.expectOne(heroService.heroesUrl);
  expect(req.request.method).toEqual('GET');

  // Respond with the mock heroes
  req.flush(expectedHeroes);
});

    it('should also work with promise', () => {

  heroService.notWorking().subscribe(
    heroes => expect(heroes).toEqual(expectedHeroes, 'should return expected heroes'),
    fail
  );

  // HeroService should have made one request to GET heroes from expected URL
  const req = httpTestingController.expectOne(heroService.heroesUrl);
  expect(req.request.method).toEqual('GET');

  // Respond with the mock heroes
  req.flush(expectedHeroes);
});

请注意,只要您从notWorking()测试中删除 promise.then 就会再次成功。

我目前无法解决在那里创建的附加主题,但这不应该影响我对承诺的问题。

我也无法解决这个承诺,因为它是从第 3 方库返回的。我尝试将其包装到 Observable ( fromPromise) 中,但这也无济于事。

在此处查看整个内容:https ://stackblitz.com/edit/angular-y21e6j

标签: angularpromiserxjsangular-test

解决方案


在一些帮助下,我发现了问题...根据https://www.joshmorony.com/testing-asynchronous-code-with-fakeasync-in-angular fakeAsync()以及flushMicroTasks()需要使用...确实它确实有效:

it('should also work with promise and fakeAsync', fakeAsync(() => {

      heroService.notWorking().subscribe(
        heroes => expect(heroes).toEqual(expectedHeroes, 'should return expected heroes'),
        fail
      );
      flushMicrotasks();

      // HeroService should have made one request to GET heroes from expected URL
      const req = httpTestingController.expectOne(heroService.heroesUrl);
      expect(req.request.method).toEqual('GET');

      // Respond with the mock heroes
      req.flush(expectedHeroes);
    }));

推荐阅读