如何在测试中模拟Angular 4.3 httpClient的错误响应 [英] How to mock Angular 4.3 httpClient an error response in testing
问题描述
我有一个拦截器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));
}
}
现在我想模拟 http.get
抛出错误,以便方法 handleError
控制错误消息。
Now I am trying to mock the http.get
to throw the error, so that method handleError
consoles the error message.
以下是我对测试用例的处理方法 auth-interceptor.service.specs.ts
Below is my approach to the test case 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();
}))
);
});
刷新响应时,我不知道如何刷新错误响应,以便方法<将在我的拦截器中调用code> handleError ,并最终调用 console.error
。文档没有任何我的情况的例子。任何帮助或建议都表示赞赏。
When flushing the response, I am not sure how to flush a error response, so that the method handleError
will be called in my interceptor and that eventually calls console.error
. Documentation doesn't have any example to my situation. Any help or suggestion is appreciated.
推荐答案
expectOne
方法 HttpTestingController
类返回一个 TestRequest
对象。这个TestRequest类有一个 flush
方法,可以用来交付
The expectOne
method in HttpTestingController
class returns a TestRequest
object. This TestRequest class has a flush
method which can be used to deliver
两个成功回复不成功。
both successful and unsuccessful responses.
我们可以通过返回一个正文以及一些额外的响应头(如果有的话)来解决请求。相关信息可以在这里找到。
We can resolve the request by returning a body along with some additional response headers (if any). Relevant info can be found here.
现在,回过头来说明如何做到这一点。您可以根据您的使用情况自定义以下代码段。
Now, coming back to the point how you can do this. You can customize the below code snippet as per your use case.
http = TestBed.get(HttpTestingController);
let response:any;
let errResponse: any;
const mockErrorResponse = {
status: 404, 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);
注意:在撰写此评论时, statusText
在 mockErrorResponse
中是必需的。相关信息可以在这里找到。
NOTE: At the time of writing this comment, statusText
is required in mockErrorResponse
. Related info can be found here.
PS :错误
TestRequest
类的方法可用于模拟网络在我们的测试用例中出错,因为它需要一个Error实例。以下代码段显示了。
P.S.: The error
method of TestRequest
class can be used to simulate network error in our test case, as it expects an instance of Error. The following code snippet shows that.
http.expectOne(someUrl).error(new ErrorEvent('network error'));
这篇关于如何在测试中模拟Angular 4.3 httpClient的错误响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!