我很难为服务编写测试,该服务从已解决的承诺的httpClient.get(...)
内部调用angular的then
。在整个应用程序(即非测试)内部,一切都按预期工作,承诺得以解决,并且从已解决的承诺数据中提取了httpClient.get
调用的URL
在测试中,即使已解决了承诺(执行了then(...)
,也从未明显执行过httpClient.get(...)
。
为了说明这个问题,我根据angular的Http Guide Testing创建了一个片段。在这里查看全部内容: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()
中进行测试,测试就会再次成功。
我目前无法解决在那里创建的其他主题,但这不应该影响我所承诺的问题。
我也无法兑现承诺,因为它是从第3方库返回的。我尝试将其包装到Observable(fromPromise
)上,但这也无济于事。
答案 0 :(得分:0)
在一些帮助下,我发现了问题...根据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);
}));