我建立了一个HttpInterceptor
,它紧跟Angular文档中的那个。
但是,我需要在拦截器中进行异步调用。我用简化的代码版本创建了StackBlitz(但语义相同)。
拦截器如下:
export class AuthInterceptor implements HttpInterceptor {
constructor(private session: SessionService, private config: ConfigurationService) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
const apiRoot = this.config.apiUrl;
if (apiRoot && req.url.startsWith(apiRoot)) {
return this.addAuth(req).pipe(switchMap(x => next.handle(x)));
} else {
return next.handle(req);
}
}
private addAuth(original: HttpRequest<any>): Observable<HttpRequest<any>> {
return from(this.session.getToken()).pipe(
map(token => {
const req = original.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
return req;
})
);
}
}
这很简单:
req.url.startsWith()
) ConfigurationService
有一个简单的string
属性,名为apiUrl
。
SessionService
具有几乎同样简单的名为getToken()
的方法,该方法返回Promise<string>
。
但是,我很难对此进行测试...
我的实际测试非常简单:
it('should add authorization header for API call', () => {
http.get('bar').subscribe();
httpMock.expectOne(req => req.headers.has('Authorization'));
});
我已经正确地嘲笑了getToken()
和apiUrl
,以便apiUrl='bar'
和getToken()
返回Promise.resolve('foobar')
。
通过addAuth()
路径时,问题似乎只有 。如果我进行反案测试,它会起作用:
it('should NOT add authorization header for non-API call', () => {
http.get('baz').subscribe();
httpMock.expectOne(req => !req.headers.has('Authorization'));
});
答案 0 :(得分:0)
因此,正如我的评论之一所述,解决方法似乎是像这样使用fakeAsync()
和tick()
:
beforeEach(()=>{
spyOn(sessionService, 'getToken').and.returnValue(Promise.resolve('foobar'));
});
it('should add authorization header for API call', fakeAsync(() => {
http.get('bar').subscribe();
tick();
httpMock.expectOne(req => req.headers.has('Authorization'));
}));
尽管有道理,但如果有人可以澄清为什么我需要tick()
...我认为解决的承诺就足够了。我确实尝试过使用await http.get().toPromise();
(并使用async
关键字-而不是函数),但这没用。