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://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);
}));
我很难为从已解决承诺的 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://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);
}));