#angular #angular-http-interceptors
Вопрос:
Я пишу приложение Angular 10. Мне нужно создать перехватчик, который будет повторять все неудачные идемпотентные HTTP-запросы. Прочитав несколько онлайн-уроков, я написал перехватчик, который, как я думал, сделает свое дело. Затем я написал тест, чтобы убедиться, что он работает. К сожалению, мой тест не провалится; даже когда я изменяю перехватчик, чтобы сделать тест неудачным, он не проваливается.
Вот перехватчик:
export class RetryInterceptor implements HttpInterceptor {
// private IDEMPOTENT_METHODS = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT', 'TRACE']; // this is the real prod code.
private IDEMPOTENT_METHODS = ['POST']; // this should cause my test to fail, but it doesn't.
constructor(private router: Router, private logger: NGXLogger) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('here'); // I've confirmed that this is being printed to the console.
if (this.IDEMPOTENT_METHODS.includes(request.method)){
console.log('there'); // I've confirmed that this is being printed to the console.
return next.handle(request)
.pipe(
retry(1));
}
else{
return next.handle(request);
}
}
}
Вот тест:
describe('RetryInterceptor', () => {
let httpTestingController: HttpTestingController;
let http: HttpClient;
let router: Router;
let location: Location;
let fixture;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
LoggerTestingModule,
RouterTestingModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: httpTranslateLoader,
deps: [HttpClient]
}
})
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: RetryInterceptor,
multi: true,
},
],
});
httpTestingController = TestBed.inject(HttpTestingController);
http = TestBed.inject(HttpClient);
router = TestBed.inject(Router);
location = TestBed.inject(Location);
fixture = TestBed.createComponent(AppRootComponent);
router.initialNavigation();
});
it('should not retry POSTs', fakeAsync( // I am expecting this to fail.
() => {
http.post('/api/resource', {}).subscribe(response => expect(response).toBeTruthy());
httpTestingController.expectOne({method: 'POST', url: '/api/resource'}).error(
new ErrorEvent('network error', { message: 'bad request' }), { status: 400 });
tick(); // the first tick is intended to make a call to the httpTestingController, which will return an error, which will be caught by my Interceptor.
tick(); // on the second tick, my Interceptor should retry the failed call. this should, in turn, fail the test, because I have not set up a second expectation.
})
);
});
Может ли кто-нибудь заметить, что я делаю не так? Мой перехватчик сломался? или мой тест провалился?
Комментарии:
1. Я не вижу логики для управления неудачным запросом в вашем
RetryInterceptor
!2. @AmirhosseinMehrvarzi Итак, цель состояла в том, чтобы в случае неудачи повторить попытку один раз. Если он снова выйдет из строя, ошибка будет передана по цепочке фильтров другому фильтру обработки ошибок, который я написал.
Ответ №1:
перехватчик в порядке. вам необходимо проверить свой контроллер тестирования http в конце теста, чтобы перехватывать неожиданные запросы:
// insert this at end of test or in an afterEach() block
httpTestingController.verify()
как правило, любой модульный тест, связанный с http-запросами, должен заканчиваться проверкой.
Документы:
https://angular.io/guide/http#testing-http-requests
https://angular.io/api/common/http/testing/HttpTestingController#verify
Комментарии:
1. Да, я почти уверен, что это сработало. Мой полный код можно найти здесь: github.com/AugustZellmer/Angular-Retry-Interceptor