angular - 角度:从已解决的 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://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);
}));
推荐阅读
- java - 正则表达式重音java
- vcl - 从 v2013.09 升级后,TeeChart VCL TSeriesBandTool 乐队仅在鼠标移动时显示
- jquery - Select2 结果位置不正确
- angular - 在 Angular 中将样式封装的 CSS 转换为 RTL
- swift - 即使父节点在移动,如何在屏幕上给每个节点相同的起始位置?
- java - 无法模拟具有泛型参数的方法
- laravel - laravel 通知未存储到我的数据库中加上错误
- php - Codeigniter、mysql、select_max 并在插入另一条记录之前加 1
- imagemagick - ImageMagick - 修剪/裁剪到连续的对象
- android - 如何使用 Volley 库在 android recyclerView 中添加搜索功能