2017-09-25 157 views
2

我試圖在Angular 4中測試一個HttpInterceptor。我發現當我打電話給HttpClient.get()時,它發生錯誤什麼時候Angular4 HttpClient.get()返回undefined?

TypeError:您提供了'undefined',其中一個流是預期的。您可以提供Observable,Promise,Array或Iterable。

http.get('/ data')何時返回undefined?

Plunkr here

import { Injectable } from '@angular/core'; 
import { TestBed, async, inject } from '@angular/core/testing'; 
import { HttpClient, HttpClientModule, HttpHandler } from '@angular/common/http'; 
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; 
import 'rxjs/add/operator/toPromise'; 


describe('AppComponent',() => { 
    beforeEach(async(() => { 
     TestBed.configureTestingModule({ 
      imports: [HttpClientTestingModule, HttpClientModule], 
      providers: [ HttpClient, HttpHandler, 
       // { 
       //  provide: HTTP_INTERCEPTORS, 
       //  useClass: AuthErrorHttpInterceptorService, 
       //  multi: true 
       // } 
      ] 
     }).compileComponents(); 
    })); 



    it('adding header test', inject([HttpClient], (http: HttpClient) => { 
     debugger; 
     const httpMock = TestBed.get(HttpTestingController); 

     // Make an HTTP GET request, and expect that it return an object 
     // of the form {name: 'Test Data'}. 
     http.get('/data') 
      .subscribe(data => expect(data['name']).toEqual('Test Data')); 

     // At this point, the request is pending, and no response has been 
     // sent. The next step is to expect that the request happened. 
     const req = httpMock.expectOne('/data'); 

     // If no request with that URL was made, or if multiple requests match, 
     // expectOne() would throw. However this test makes only one request to 
     // this URL, so it will match and return a mock request. The mock request 
     // can be used to deliver a response or make assertions against the 
     // request. In this case, the test asserts that the request is a GET. 
     expect(req.request.method).toEqual('GET'); 

     // Next, fulfill the request by transmitting a response. 
     req.flush({name: 'Test Data'}); 

     // Finally, assert that there are no outstanding requests. 
     httpMock.verify(); 
    })); 
}); 

類型錯誤:其中一個流,預計您提供 '未定義'。您可以提供Observable,Promise,Array或Iterable。

編輯:我見過問題Error while unit testing HttpClientModule (Angular 4.3+)和導入的HttpClientModule,但我仍然得到錯誤。此外,我不包括我的攔截器組件,直到我解決這個錯誤,所以有問題不能在那裏。

編輯:const req = httpMock.expectOne('/data');這一行從不執行,因爲錯誤被從線拋出上述

編輯:解決方案是從所述提供者陣列

+1

你採用t他是HTTP測試模塊,但您從未實際選擇請求或刷新響應。閱讀相關文檔:https://angular.io/guide/http#testing-http-requests – jonrsharpe

+0

好的謝謝,這可能是爲什麼我得到錯誤。讓我檢查 –

+0

嗨jonrsharpe,我編輯了問題的代碼從文檔,但我仍然得到錯誤,你提供'未定義'在哪裏預期流 –

回答

1

FYI最終溶液中去除「HttpClient的,HttpHandler的」

import { AuthErrorHttpInterceptorService } from './authErrorHttpInterceptor.service'; 
import { TestBed, inject, fakeAsync, tick } from '@angular/core/testing'; 
import { RouterTestingModule } from '@angular/router/testing'; 
import { LoginComponent } from './../../routes/login/login.component'; 
import { Router } from '@angular/router'; 
import { HttpHandler, HttpRequest, HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http'; 
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; 
import 'rxjs/add/operator/catch'; 
import { FormsModule } from '@angular/forms'; 
import { Location } from '@angular/common'; 

describe('AuthErrorHttpInterceptorService',() => { 
    beforeEach(() => { 
     TestBed.configureTestingModule({ 
      declarations: [LoginComponent], 
      imports: [HttpClientTestingModule, HttpClientModule, 
       RouterTestingModule.withRoutes([{ path: 'login', component: LoginComponent }]), 
       FormsModule 
      ], 
      providers: [ 
       { 
        provide: HTTP_INTERCEPTORS, 
        useClass: AuthErrorHttpInterceptorService, 
        multi: true 
       }, 
       Location 
      ] 
     }); 
    }); 

    // https://angular.io/guide/http#testing-http-requests 
    it('subscribe should return the given data', inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { 
     const myGet = http.get('/data'); 
     myGet.subscribe((data) => { 
      expect(data['name']).toEqual('Test Data'); 
      expect(data['name']).not.toEqual('Test Datas'); 
     }); 
     const req = httpMock.expectOne('/data'); 
     expect(req.request.method).toEqual('GET'); 
     req.flush({ name: 'Test Data' }); 
     httpMock.verify(); 
    })); 

    it('should redirect unauthorised requests to /api/data', inject([HttpClient, HttpTestingController], fakeAsync((http: HttpClient, httpMock: HttpTestingController) => { 
     const myGet = http.get('/api/data'); 
     myGet.subscribe((data) => { 
      expect(data['name']).toEqual('Test Data'); 
     }, (error) => { 
      let router = TestBed.get(Router); 
      let location = TestBed.get(Location); 
      tick(); 
      expect(location.path()).toBe('/login'); 
     }); 
     const req = httpMock.expectOne('/api/data'); 
     expect(req.request.method).toEqual('GET'); 
     req.flush({ name: 'Test Data' }, { status: 401, statusText: 'Server Error' }); 
     httpMock.verify(); 
    }))); 

    it('should not redirect unauthorised requests to /api/authorization/data', inject([HttpClient, HttpTestingController], fakeAsync((http: HttpClient, httpMock: HttpTestingController) => { 
     const myGet = http.get('/api/authorization/data'); 
     myGet.subscribe((data) => { 
      expect(data['name']).toEqual('Test Data'); 
     }, (error) => { 
      let router = TestBed.get(Router); 
      let location = TestBed.get(Location); 
      tick(); 
      expect(location.path()).toBe(''); 
     }); 
     const req = httpMock.expectOne('/api/authorization/data'); 
     expect(req.request.method).toEqual('GET'); 
     req.flush({ name: 'Test Data' }, { status: 401, statusText: 'Server Error' }); 
     httpMock.verify(); 
    }))); 

    it('should not redirect http: 200 requests to /api/data', inject([HttpClient, HttpTestingController], fakeAsync((http: HttpClient, httpMock: HttpTestingController) => { 
     const myGet = http.get('/api/authorization/data'); 
     myGet.subscribe((data) => { 
      expect(data['name']).toEqual('Test Data'); 
     }, (error) => { 
      let router = TestBed.get(Router); 
      let location = TestBed.get(Location); 
      tick(); 
      expect(location.path()).toBe(''); 
     }); 
     const req = httpMock.expectOne('/api/authorization/data'); 
     expect(req.request.method).toEqual('GET'); 
     req.flush({ name: 'Test Data' }, { status: 200, statusText: 'success' }); 
     httpMock.verify(); 
    }))); 
}); 

攔截

import { Injectable, forwardRef } from '@angular/core'; 
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/do'; 
import { Router } from '@angular/router'; 
import { Inject } from '@angular/core'; 

@Injectable() 
export class AuthErrorHttpInterceptorService implements HttpInterceptor { 
    constructor(private router: Router) { } 
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { 
     return next.handle(req).do(event => { }, err => { 
      if (err instanceof HttpErrorResponse 
       && err.status === 401 
       && !err.url.match('/api/authorization/') 
       && err.url.match('/api/')) { 

       this.router.navigate(['login']); 
      } 
     }); 
    } 
} 
相關問題