2017-09-25 99 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']); 
      } 
     }); 
    } 
} 
相关问题