web-dev-qa-db-fra.com

Échec: impossible de résoudre tous les paramètres de MatDialogRef: (?,?,?). tests unitaires Angular

Je suis nouveau dans le développement angular et plus vers les tests unitaires en utilisant du jasmin. J'ai créé un composant pour semer une boîte de dialogue en utilisant angular matériel MatDialogRef, MAT_DIALOG_DATA de @ angulaire/matériel. Le composant fonctionne bien mais les tests unitaires me donnent une erreur que je ne suis pas en mesure de résoudre.

J'ai vraiment besoin de cela pour travailler et toute aide serait appréciée .... Merci d'avance .. !!!

Veuillez trouver mon code ci-dessous:

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 { }

supprimer le composant client

        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();
      });
    });

erreur de karma

        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

Lorsque j'essayais de tester le composant de boîte de dialogue, j'ai rencontré le même problème. Ma solution est basée sur le test de dialogue dans le code source du matériau angulaire.

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);
  });
});

Je ne suis pas sûr que ce soit la bonne approche, toujours moi-même débutant.

11
Felix

Selon vos besoins, une approche plus simple consiste à injecter un faux fournisseur MatDialog qui a un espion jasmin pour les méthodes proches ou ouvertes. Par exemple:

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();
  });
});

Ce Gist est, n'injectez pas l'instance réelle de MatDialog ou MatDialogRef dans votre test. Injectez un faux objet à la place avec un espion jasmin qui peut vous dire si une méthode a été appelée.

10
Phil