web-dev-qa-db-ja.com

失敗:MatDialogRefのすべてのパラメーターを解決できません:(?、?、?)。単体テストAngularプロジェクト

私はangularの開発が初めてで、ジャスミンを使用した単体テストの方が新しいです。 @ angular/materialからangular material MatDialogRef、MAT_DIALOG_DATAを使用してダイアログをsoくコンポーネントを作成しました。コンポーネントは正常に機能していますが、ユニットテストでエラーが発生し、解決できません。

私はこれが機能するために本当に必要であり、どんな助けも感謝します....事前に感謝します.. !!!

以下の私のコードを見つけてください:

app.module.ts

        import { BrowserModule } from '@angular/platform-browser';
    import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
    import { HttpClientModule, HttpClient } from '@angular/common/http';
    import { HttpModule } from '@angular/http';
    import { RouterModule, Routes } from '@angular/router';
    import 'hammerjs';
    import { NgxPhoneSelectModule } from 'ngx-phone-select';
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    import { FormsModule, ReactiveFormsModule } from '@angular/forms';
    import { MatInputModule, MatButtonModule, MatSelectModule } from '@angular/material';
    import { MatGridListModule } from '@angular/material';
    import { MatTableModule } from '@angular/material';
    import { MatDialogModule} from '@angular/material';
    import { MatCardModule} from '@angular/material';
    import { MaterialModule } from './modules/material/material.module';


    import { AppComponent } from './app.component';
    import { CustomerComponent } from './components/customer/customer.component';
    import { LoginComponent } from './components/login/login.component';
    import { ForgetPasswordComponent } from './components/forget-password/forget-password.component';
    import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
    import { DashboardComponent } from './components/dashboard/dashboard.component';

    import { LoaderService } from './services/loader.service';
    import { CustomerDataService } from './services/customer-data.service';
    import { UserService } from './services/user/user.service';


    import { HeaderComponent } from './components/header/header.component';
    import { UpdateCustomerComponent } from './components/update-customer/update-customer.component';
    import { AuthService } from './services/auth.service';
    import { AuthGuard } from './services/auth/auth.guard';
    import { DeleteCustomerComponent } from './components/delete-customer/delete-customer.component';
    import { FooterComponent } from './components/footer/footer.component';
    const appRoutes: Routes = [
      {
        path: '',
        component: LoginComponent
      },
      {
        path: 'create-customer',
        component: CustomerComponent,
        //        canActivate: [AuthGuard] // ristrict direct access of links
      },
      {
        path: 'forget-password',
        component: ForgetPasswordComponent,
        //        canActivate: [AuthGuard] // ristrict direct access of links
      },
      {
        path: 'dashboard',
        component: DashboardComponent,
        //        canActivate: [AuthGuard] // ristrict direct access of links
      },
      {
        path: 'update-customer',
        component: UpdateCustomerComponent,
        //        canActivate: [AuthGuard] // ristrict direct access of links
      },
      {
        path: '**',
        component: PageNotFoundComponent
      }
    ];

    @NgModule({
      declarations: [
        AppComponent,
        CustomerComponent,
        LoginComponent,
        ForgetPasswordComponent,
        PageNotFoundComponent,
        DashboardComponent,
        HeaderComponent,
        UpdateCustomerComponent,
        DeleteCustomerComponent,
        FooterComponent
      ],
      imports: [
        BrowserModule,
        HttpClientModule,
        HttpModule,
        RouterModule.forRoot(appRoutes),
        NgxPhoneSelectModule,
        BrowserAnimationsModule,
        FormsModule,
        ReactiveFormsModule,
        MatInputModule,
        MatButtonModule,
        MatSelectModule,
        MatGridListModule,
        MatTableModule,
        MaterialModule
      ],
      entryComponents: [
          DeleteCustomerComponent
      ],
      schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
    providers: [LoaderService, AuthService, AuthGuard, UserService, CustomerDataService],

      bootstrap: [AppComponent]
    })
    export class AppModule { }

顧客コンポーネントの削除

        import { Component, OnInit, Inject } from '@angular/core';
    import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';

    import { Router} from '@angular/router';
    @Component({
      selector: 'app-delete-customer',
      templateUrl: './delete-customer.component.html',
      styleUrls: ['./delete-customer.component.scss']
    })
    export class DeleteCustomerComponent implements OnInit {

      constructor(private router: Router, public deleteCustDialogRef: MatDialogRef<DeleteCustomerComponent>, @Inject(MAT_DIALOG_DATA) public data: string) { }

      ngOnInit() {
      }

    onClosedeleteCustomer() {
        this.deleteCustDialogRef.close('confirm');
        this.router.navigate(['./dashboard']);
      }
      onCloseCancel() {
        this.deleteCustDialogRef.close('cancel');

    }
    }

delete-customer.component.spec.ts

        import { async, ComponentFixture, TestBed } from '@angular/core/testing';
    import {RouterTestingModule} from '@angular/router/testing';
    import { DeleteCustomerComponent } from './delete-customer.component';
    import { MaterialModule } from '../../modules/material/material.module';
    import { MatDialogRef, MAT_DIALOG_DATA, MatDialog, MatDialogModule  } from '@angular/material';
    describe('DeleteCustomerComponent', () => {
      let component: DeleteCustomerComponent;
      let fixture: ComponentFixture<DeleteCustomerComponent>;

      beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [ DeleteCustomerComponent ],
          imports: [ MaterialModule, RouterTestingModule, MatDialogModule ],
          providers : [ MatDialogRef, MAT_DIALOG_DATA, MatDialog ]
        })
        .compileComponents();
      }));

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

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

カルマエラー

        DeleteCustomerComponent should create
        Failed: Can't resolve all parameters for MatDialogRef: (?, ?, ?).
        Error: Can't resolve all parameters for MatDialogRef: (?, ?, ?).
        at syntaxError (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:485:22)
        at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15662:1)
        at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver._getTypeMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15497:1)
        at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver._getInjectableMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15477:1)
        at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver.getProviderMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15837:1)
        at http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15748:1
        at Array.forEach (<anonymous>)
        at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver._getProvidersMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15708:1)
        at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver.getNgModuleMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15276:1)
        at JitCompiler.webpackJsonp.../../../compiler/esm5/compiler.js.JitCompiler._loadModules (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler
12
pranay anand

ダイアログコンポーネントをテストしようとしたときに、同じ問題が発生しました。私のソリューションは、角度材料のソースコードの dialog test に基づいています。

import { MyDialogComponent } from './mydialog.component';
import { async, TestBed, inject } from '@angular/core/testing';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatDialog } from '@angular/material/dialog';
import { OverlayContainer } from '@angular/cdk/overlay';

describe('MyDialogComponent', () => {
  let dialog: MatDialog;
  let overlayContainer: OverlayContainer;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MyDialogComponent],
      imports: [
        MatDialogModule,
      ]
    });

    TestBed.overrideModule(BrowserDynamicTestingModule, {
      set: {
        entryComponents: [MyDialogComponent]
      }
    });

    TestBed.compileComponents();
  }));

  beforeEach(inject([MatDialog, OverlayContainer],
    (d: MatDialog, oc: OverlayContainer) => {
      dialog = d;
      overlayContainer = oc;
    })
  );

  afterEach(() => {
    overlayContainer.ngOnDestroy();
  });

  it('should open a dialog with a component', () => {
    const dialogRef = dialog.open(MyDialogComponent, {
      data: { param: '1' }
    });

    // verify
    expect(dialogRef.componentInstance instanceof MyDialogComponent).toBe(true);
  });
});

しかし、これが正しいアプローチであるかどうかはわかりませんが、まだ初心者です。

11
Felix

ニーズに応じて、より簡単なアプローチは、closeメソッドまたはopenメソッド用のジャスミンスパイを持つ模擬MatDialogプロバイダーを注入することです。例えば:

import { MyDialogComponent } from './mydialog.component';
import { async, TestBed, inject } from '@angular/core/testing';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { MatDialog } from '@angular/material/dialog';

describe('MyDialogComponent', () => {
  const mockDialogRef = {
    close: jasmine.createSpy('close')
  };

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MyDialogComponent],
      imports: [MatDialogModule],
      providers: [
        {
          provide: MatDialogRef,
          useValue: mockDialogRef
        }
      ]
    })
    .compileComponents();
  }));

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

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

  it('#onClosedeleteCustomer should close the dialog', () => {
    component.onClosedeleteCustomer();
    expect(mockDialogRef.close).toHaveBeenCalled();
  });
});

このGistは、テストにMatDialogまたはMatDialogRefの実際のインスタンスを挿入しないでください。メソッドが呼び出されたかどうかを伝えることができるジャスミンスパイを代わりにモックオブジェクトに注入します。

10
Phil