Как проверить перехватчик, который вызывает наблюдаемое в Angular 6+?
Я построил HttpInterceptor
это близко следует за тем в угловой документации.
Однако мне нужно было сделать асинхронный вызов как часть моего перехватчика. Я создал 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;
})
);
}
}
Это довольно просто:
- проверьте, требует ли URL, по которому мы звоним, наш токен (
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'));
});
1 ответ
Итак, как упоминалось в одном из моих комментариев, исправление, похоже, заключается в использовании 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
Ключевое слово - не функция), но это не сработало.