angular:httpClient.get 来自已解决的 Promise 测试失败

angular: httpClient.get from resolved Promise fails from test

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

然而在测试中,即使 promise 已解决(then(...) 已执行),httpClient.get(...) 显然从未执行过。

为了说明问题,我根据 angular 的 Http 指南测试创建了一个片段。在这里查看全部内容:https://stackblitz.com/edit/angular-y21e6j

带有 promise 的测试失败了:

Error: Expected one matching request for criteria "Match URL: api/heroes", found none.

总的来说我有两个功能:

  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;
  }

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

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

在一些帮助下,我发现了问题...根据 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);
    }));