单元测试HttpClientModule时出错(Angular 4.3+)

时间:2017-07-26 12:25:26

标签: angular

我正在探索新的Angular HttpClientModule并遇到一个无法解释的错误。该模块足够新,我还无法找到有关如何进行单元测试的任何有用信息,官方文档也没有任何示例。

该应用包含一项服务,该方法将网址传递给http.get。当我在浏览器上下文(又名ng serve)中调用此方法时,http调用正常执行。在单元测试的上下文中调用时,我收到以下错误:

TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

这是使用Angular CLI生成的最小应用程序。这是相关的代码:

app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts:

import { Component, OnInit } from '@angular/core';
import { TestService } from './test.service'

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [TestService]
})
export class AppComponent {
  title = 'app';

  constructor(private testSvc: TestService) {}

  ngOnInit() {
    this.testSvc.executeGet('http://www.example.com');
  }
}

test.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class TestService {
  constructor(private http:HttpClient) {}

  executeGet(url:string) {
    this.http.get(url)
      .subscribe(
        data => console.log('success', data),
        error => console.log('error', error)
    );
  }
}

test.service.spec.ts:

import { HttpClient, HttpHandler } from '@angular/common/http';
import { TestBed, inject } from '@angular/core/testing';
import { TestService } from './test.service';

describe('TestService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [HttpClient, HttpHandler, TestService]
    });
  });

  it('should executeGet', inject([TestService], (svc: TestService) => {
    expect(svc.executeGet).toBeDefined();
    // this is where the 'undefined' error occurs
    svc.executeGet('http://www.example.com'); 
  }));
});

任何指导或指示非常感谢。

2 个答案:

答案 0 :(得分:3)

最近我遇到了完全相同的问题,其中包含错误消息:

TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

对我来说,此错误的来源并未正确使用 HttpInterceptor 。如果您还提供自定义 HttpInterceptor ,请确保正确使用它。在以下代码段中,请注意如果错误状态不是401,我错过了返回Observable, Promise, Array, or Iterable的方式。默认情况下,undefined方法返回intercept而不是Observable, Promise, Array, or Iterable,因此有角度抱怨关于那个。

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).catch(err => {
      if(err instanceof HttpErrorResponse) {
        if(err.status === 401) {
          this.store.dispatch(this.authAction.unauthorized(err));
          return Observable.throw(err);
        }
      }
    })
  }

,修复方法是以下代码段。

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).catch(err => {
      if(err instanceof HttpErrorResponse) {
        if(err.status === 401) {
          this.store.dispatch(this.authAction.unauthorized(err));
        }
      }
      return Observable.throw(err); //Actually this line of code
    })
  }

答案 1 :(得分:1)

导致缺少HttpClientModule

Here is the working example on plnkr

describe('TestService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientModule],
      providers: [TestService]
    });
  });

  it('should executeGet', () => {
    const testService = TestBed.get(TestService);

    expect(testService.executeGet).toBeDefined();
    testService.executeGet('http://www.example.com');
  }));
});