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