5

错误响应我有一个低于interceptor auth-interceptor.service.ts如何嘲笑角4.3 HttpClient的测试

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

当冲洗的反应,我不知道如何刷新一个错误响应,因此该方法handleError会在我的拦截和被称为最终请致电console.error。文档对我的情况没有任何例子。任何帮助或建议表示赞赏。

+1

您的'req'对象是'TestRequest'类的一个实例。它也有'error()'方法。你有没有尝试类似'req.error(new ErrorEvent('fail'),{status:404});'? –

回答

6

expectOne方法在HttpTestingController类中返回一个TestRequest对象。此TestRequest类具有flush方法,可用于递送

成功和不成功的答复。

我们可以通过返回一个主体以及一些额外的响应头(如果有的话)来解决请求。相关信息可以在here找到。

现在,回到关于如何做到这一点的问题。您可以根据您的用例自定义下面的代码片段。

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。相关信息可参见here

P.S.TestRequest类的error方法可用于在我们的测试案例中模拟网络错误,因为它期望一个Error实例。以下代码片段显示了这一点。

http.expectOne(someUrl).error(new ErrorEvent('network error'));