代码之家  ›  专栏  ›  技术社区  ›  Sai Ram Gupta

如何在测试中模拟Angular 4.3 httpClient的错误响应

  •  45
  • Sai Ram Gupta  · 技术社区  · 8 年前

    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));
        }
    }
    

    现在我试着嘲笑 http.get handleError 控制台错误消息。

    下面是我的测试用例方法 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();
            }))
        );
    });
    

    刷新响应时,我不确定如何刷新错误响应,因此方法 手柄错误 将在我的拦截器中调用,并最终调用 console.error

    1 回复  |  直到 8 年前
        1
  •  94
  •   EriF89 Silas Ray    7 年前

    这个 expectOne 中的方法 HttpTestingController 类返回a TestRequest 对象这个TestRequest类有一个 flush 可用于交付的方法

    成功和不成功的回答。

    here .

    现在,回到你该如何做到这一点。您可以根据您的用例自定义以下代码段。

    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);
    

    :在撰写本评论时, statusText 中需要 mockErrorResponse here .

    附笔。 error 方法 测试请求 类可以用于在我们的测试用例中模拟网络错误,因为它需要一个错误实例。下面的代码段显示了这一点。

    http.expectOne(someUrl).error(new ErrorEvent('network error'));
    
    推荐文章