J'ai un ci-dessous interceptor auth-interceptor.service.ts
import {Injectable, Injector} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {Cookie} from './cookie.service';
import {Router} from '@angular/router';
import {UserService} from './user.service';
import {ToasterService} from '../toaster/toaster.service';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private injector: Injector) {}
private handleError(err: HttpErrorResponse): Observable<any> {
let errorMsg;
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
errorMsg = `An error occurred: ${err.error.message}`;
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
errorMsg = `Backend returned code ${err.status}, body was: ${err.error}`;
}
if (err.status === 401 || err.status === 403) {
this.injector.get(UserService).purgeAuth();
this.injector.get(ToasterService).showError(`Unauthorized`, errorMsg);
this.injector.get(Router).navigateByUrl(`/login`);
}
console.error(errorMsg);
return Observable.throw(errorMsg);
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Clone the request to add the new header.
const authReq = req.clone({headers: req.headers.set(Cookie.tokenKey, Cookie.getToken())});
// Pass on the cloned request instead of the original request.
return next.handle(authReq).catch(err => this.handleError(err));
}
}
Maintenant j'essaie de me moquer du http.get
pour renvoyer l'erreur, de sorte que la méthode handleError
console le message d'erreur.
Ci-dessous, mon approche du cas de test auth-interceptor.service.specs.ts
import {async, inject, TestBed} from '@angular/core/testing';
import {AuthInterceptor} from './auth-interceptor.service';
import {ApiService} from './api.service';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {environment} from '../../../environments/environment';
describe(`AuthInterceptor`, () => {
const somePath = `/somePath`;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [AuthInterceptor, ApiService]
});
});
it(`should be created`, inject([AuthInterceptor], (service: AuthInterceptor) => {
expect(service).toBeTruthy();
}));
it(`should log an error to the console on error on get()`, async(inject([ApiService, HttpTestingController],
(apiService: ApiService, httpMock: HttpTestingController) => {
spyOn(console, 'error');
apiService.get(somePath).subscribe((res) => {
console.log(`in success:`, res);
}, (error) => {
console.log(`in error:`, error);
});
const req = httpMock.expectOne(`${environment.apiUri}${somePath}`);
req.flush({
type: 'ERROR',
status: 404,
body: JSON.stringify({color: `blue`})
});
expect(console.error).toHaveBeenCalled();
}))
);
});
Lors du vidage de la réponse, je ne sais pas comment vider une réponse d'erreur, de sorte que la méthode handleError
soit appelée dans mon intercepteur et que finalement, elle appelle console.error
. La documentation n'a pas d'exemple à ma situation. Toute aide ou suggestion est appréciée.
La méthode expectOne
de la classe HttpTestingController
renvoie un objet TestRequest
. Cette classe TestRequest a une méthode flush
qui peut être utilisée pour livrer
les réponses réussies et non réussies.
Nous pouvons résoudre la demande en renvoyant un corps avec quelques en-têtes de réponse supplémentaires (le cas échéant). Des informations pertinentes peuvent être trouvées ici .
Revenons maintenant à la façon dont vous pouvez y arriver. Vous pouvez personnaliser l'extrait de code ci-dessous selon votre cas d'utilisation.
http = TestBed.get(HttpTestingController);
let response: any;
let errResponse: any;
const mockErrorResponse = { status: 400, statusText: 'Bad Request' };
const data = 'Invalid request parameters';
apiService.get(somePath).subscribe(res => response = res, err => errResponse = err);
http.expectOne('url/being/monitored').flush(data, mockErrorResponse);
expect(errResponse).toBe(data);
[~ # ~] note [~ # ~] : Au moment de la rédaction de ce commentaire, statusText
est requis dans mockErrorResponse
. Des informations connexes peuvent être trouvées ici .
PS : La méthode error
de TestRequest
class peut être utilisée pour simuler une erreur réseau dans notre cas de test, car elle attend une instance de Error. L'extrait de code suivant montre cela.
http.expectOne(someUrl).error(new ErrorEvent('network error'));