【问题标题】:TypeError: _this.handler.handle is not a function errorTypeError: _this.handler.handle 不是函数错误
【发布时间】:2018-12-24 03:45:28
【问题描述】:

我收到这个错误,this.handler.handle 不是我在 Angular 6 中使用 karma/jasmine 进行单元测试的函数。当我在项目文件夹中键入“ng test”命令时,此错误出现在我的命令行中。

Chrome 67.0.3396 (Windows 10.0.0) AppComponent should create FAILED    
Failed: _this.handler.handle is not a function
TypeError: _this.handler.handle is not a function

对于应该在此处创建 AppComponent 的测试是我的 .spec 文件

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule, FormBuilder } from '@angular/forms';
import { HttpClientModule, HttpClient, HttpHandler } from '@angular/common/http';
describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [FormsModule, RouterTestingModule, HttpClientModule],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      declarations: [AppComponent],
      providers: [HttpClientModule, HttpClient, HttpHandler]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', async(() => {
    expect(component).toBeTruthy();
  }));
});

这是我的 app.component.ts 文件

import { Component, ViewChild, OnInit } from '@angular/core';
import { AuthorizationService } from 'src/app/authorization.service';
import { Router } from '@angular/router';
import { MdcDrawer } from '@angular-mdc/web';
import { tap, catchError } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  @ViewChild(MdcDrawer) sidenav: MdcDrawer;
  flip = false;

  constructor(private router: Router, private authorizationService: AuthorizationService) {
    this.authorizationService.getAuthorization().subscribe();
  }

  toggleState() {
    if (this.flip) {
      this.flip = false;
    } else {
      this.flip = true;
    }
  }

  goToPage(route: String) {
    this.router.navigate([route]).catch(err => {
      console.log(err);
    });
    this.sidenav.close();
  }

  close() {
    console.log('CLOSE');
    this.sidenav.close();
  }
}

这是我的 app.module.ts 文件:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { HttpModule } from '@angular/http';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { LayoutModule } from '@angular/cdk/layout';
import * as MATERIAL_MODULES from '@angular/material/';
import * as MDC_MODULES from '@angular-mdc/web';
import { TrackUpdateComponent } from './track-update/track-update.component';
import { TrackUpdatePromptComponent } from './track-update-prompt/track-update-prompt.component';
import { NavigationBarComponent } from './navigation-bar/navigation-bar.component';
import { ActionToolbarComponent } from './action-toolbar/action-toolbar.component';
import { SaveButtonToolbarComponent } from './save-button-toolbar/save-button-toolbar.component';
import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
import { EquipmentCardComponent } from './equipment-card/equipment-card.component';
import { EquipmentCardListComponent } from './equipment-card-list/equipment-card-list.component';
import { ListOptionsComponent } from './list-options/list-options.component';
import { EquipmentCardLoadingComponent } from './equipment-card-loading/equipment-card-loading.component';
import { GoToTopComponent } from './go-to-top/go-to-top.component';
import { TapActionListComponent } from './tap-action-list/tap-action-list.component';
import { JumpActionComponent } from './jump-action/jump-action.component';
import { GlobalErrorsComponent } from './global-errors/global-errors.component';
import { SwitchActionListComponent, AssignTrackForm } from './switch-action-list/switch-action-list.component';
import { AddActionComponent } from './add-action/add-action.component';
import { ErrorHandler } from './global-errors/error_handler';
import { RequestInterceptor } from './global-errors/http_interceptor';
import { ActionService } from './action.service';
import { TrackIdService } from './track-id-service.service';
import { TrackInquiryService } from './track-inquiry.service';
import { UserPreferenceService } from './user-preference.service';
import { AuthorizationService } from './authorization.service';
import { EquipmentInsertCardComponent } from './equipment-insert-card/equipment-insert-card.component';
import { LoadingIconComponent } from './loading-icon/loading-icon.component';

@NgModule({
  declarations: [
    AppComponent,
    TrackUpdatePromptComponent,
    NavigationBarComponent,
    TrackUpdateComponent,
    ActionToolbarComponent,
    SaveButtonToolbarComponent,
    EquipmentCardComponent,
    EquipmentCardListComponent,
    ListOptionsComponent,
    EquipmentCardLoadingComponent,
    GoToTopComponent,
    TapActionListComponent,
    JumpActionComponent,
    GlobalErrorsComponent,
    SwitchActionListComponent,
    AssignTrackForm,
    AddActionComponent,
    EquipmentInsertCardComponent,
    LoadingIconComponent
  ],
  entryComponents: [GlobalErrorsComponent, AssignTrackForm],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    LayoutModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule,
    MDC_MODULES.MdcButtonModule,
    MDC_MODULES.MdcCheckboxModule,
    MDC_MODULES.MdcFormFieldModule,
    MDC_MODULES.MdcToolbarModule,
    MDC_MODULES.MdcIconModule,
    MDC_MODULES.MdcListModule,
    MDC_MODULES.MdcSelectModule,
    MDC_MODULES.MdcAppBarModule,
    MDC_MODULES.MdcIconToggleModule,
    MDC_MODULES.MdcDrawerModule,
    MDC_MODULES.MdcTextFieldModule,
    MDC_MODULES.MdcDialogModule,
    MATERIAL_MODULES.MatButtonModule,
    MATERIAL_MODULES.MatCheckboxModule,
    MATERIAL_MODULES.MatMenuModule,
    MATERIAL_MODULES.MatIconModule,
    MATERIAL_MODULES.MatTableModule,
    MATERIAL_MODULES.MatCardModule,
    MATERIAL_MODULES.MatInputModule,
    MATERIAL_MODULES.MatSelectModule,
    MATERIAL_MODULES.MatToolbarModule,
    MATERIAL_MODULES.MatListModule,
    MATERIAL_MODULES.MatTooltipModule,
    MATERIAL_MODULES.MatSortModule,
    MATERIAL_MODULES.MatDialogModule,
    MATERIAL_MODULES.MatSlideToggleModule,
    MATERIAL_MODULES.MatSidenavModule,
    MATERIAL_MODULES.MatAutocompleteModule,
    MATERIAL_MODULES.MatSnackBarModule,
    MATERIAL_MODULES.MatExpansionModule
  ],
  providers: [
    HttpModule,
    HttpClientModule,
    HttpClient,
    ErrorHandler,
    ActionService,
    TrackIdService,
    TrackInquiryService,
    UserPreferenceService,
    AuthorizationService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: RequestInterceptor,
      multi: true
    }
  ],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {}

有人可以帮忙吗?我会很感激。

【问题讨论】:

  • 从 .spec.ts 和 NgModule 的提供者数组中删除 HttpClientModule

标签: angular karma-jasmine httphandler


【解决方案1】:

对我来说,这个问题来自于尝试在 TestBed.configureTestingModule 的提供程序中包含 HttpClient 和 HttpHandler,如下所示:

providers: [
    HttpClient,
    HttpHandler
]

这一直在抛出_TypeError: this.handler.handle is not a function 的错误

为了解决这个问题,我发现我可以从提供程序中删除 HttpClient 和 HttpHandler,而是将 HttpClientTestingModule 添加到我的导入中,如下所示:

imports: [
    HttpClientTestingModule
]

这为我在 Angular 7 的 Karma 单元测试中解决了这个特殊错误。

【讨论】:

  • 我必须添加建议的“HttpClientTestingModule”(谢谢!)并将“HttpClient”保留在提供程序中。
【解决方案2】:

我发现在我上次的 IT 声明之后添加以下内容为我解决了问题。

afterEach(() => {
    TestBed.resetTestingModule();
});

【讨论】:

    【解决方案3】:

    我认为代码的问题不止一个。

    我发现的第一个问题和这个问题类似:Angular5 / ng test ERROR : TypeError: this.handler.handle is not a function

    在你的 app.component.ts 你有这行:

    this.authorizationService.getAuthorization().subscribe();
    

    您需要告诉您的代码如何处理订阅返回的值,例如:

    this.authorizationService.getAuthorization().subscribe(
      x => console.log('Observer got a next value: ' + x),
      err => console.error('Observer got an error: ' + err),
      () => console.log('Observer got a complete notification')
    ); 
    

    您可以在这里阅读更多内容:https://angular.io/guide/observables

    我发现的第二个问题是,在 .spec 文件中,您没有在测试平台中提供 AuthorizationService(您可能还必须提供其他一些东西)。这是一个很好的 Angular 测试指南,即使它是为 Angular 5 编写的,也适用于版本 6:https://codecraft.tv/courses/angular/unit-testing/angular-test-bed/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      • 2020-07-29
      相关资源
      最近更新 更多