Saltar al contenido

dialogRef.afterClosed no es una función

Solución:

He llevado la respuesta de Sam Tsai un paso más allá y he creado un archivo de código auxiliar para ser más conciso. Aquí está el contenido del archivo stub:

import { of } from 'rxjs';

/* 
  The default behavior is to test that the user clicked 'OK' in the dialog.
    To reset to this behavior (if you've previously tested 'Cancel'),
    call setResult(true).     

  If you want to test that the user clicked 'Cancel' in the dialog, 
    call setResult(false).
*/

export class MatDialogStub {
  result: boolean = true;

  setResult(val: boolean) {
    this.result = val;
  }

  open() {
    return {afterClosed: () => of(this.result) };
  }
}

Luego, en el archivo .spec.ts, usa el código auxiliar de esta manera:

import { MatDialogStub } from '../../../../testing/mat-dialog-stub'; // <--- (import here)

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  const dialogStub = new MatDialogStub(); // <--- (declare here)

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [],
      declarations: [ MyComponent ],
      providers: [
        { provide: MatDialog,  useValue: dialogStub } // <--- (use here)
      ]
    })
      .compileComponents();
  }));
  //...
});

Y en la prueba real, puede establecer el valor de retorno en verdadero o falso para simular hacer clic en el botón ‘Aceptar’ o ‘Cancelar’ respectivamente llamando a la función setResult ():

dialogStub.setResult(true); 

o

dialogStub.setResult(false);

Nota: el valor predeterminado para las pruebas de stub es ‘OK’ para que no tenga que llamar a la función si solo está probando ‘OK’.

Las pruebas a continuación primero simulan un ‘Cancelar’ y luego un clic en el botón ‘Aceptar’:

it(`should not call 'delete' when Submit button pressed and user cancels`, async(() => {
    component.apis = [new Api({name: 'abc'})];
    component.displayPermissions = [new Permission({name: 'abc'})];
    dialogStub.setResult(false); // <--- (call the function here)
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;   
    compiled.querySelector('button').click();
    expect(permissionService.delete.calls.count()).toBe(0, 'no calls');
}));

it(`should call 'delete' once when Submit button pressed and not cancelled`, async(() => {
    component.apis = [new Api({name: 'abc'})];
    component.displayPermissions = [new Permission({name: 'abc'})];
    dialogStub.setResult(true); // <--- (call the function here)
    fixture.detectChanges();        
    const compiled = fixture.debugElement.nativeElement;    
    compiled.querySelector('button').click();
    expect(permissionService.delete.calls.count()).toBe(1, 'one call');
}));

Respuesta original

He buscado en todas partes una forma concisa de burlarme del MatDialog y deshacerme del error que estaba obteniendo dialogRef.afterClosed no es una función. (vea algunos enlaces que probé en la parte inferior). Nada de lo que encontré fue la solución correcta hasta que probé la respuesta de Sam Tsai a esta pregunta. Fue una solución simple que eliminó todos mis errores y me permitió probar correctamente mi aplicación. Ojalá hubiera encontrado esto antes de pasar tanto tiempo en todos los demás enlaces.

Esta es la prueba unitaria que estaba fallando; falló en el evento (‘button’). click porque abre el MatDialog y solo realiza la eliminación si el diálogo devuelve verdadero. No sabía cómo burlarme del MatDialog correctamente para que ocurriera la eliminación:

it("should call 'delete' once when Submit button pressed and not cancelled", async(() => {
    component.apis = [new Api({name: 'abc'})];
    component.displayPermissions = [new Permission({name: 'abc'})];
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    compiled.querySelector('button').click();
    expect(permissionService.delete.calls.count()).toBe(1, 'one call');
}));

Lo arreglé agregando esto:

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;

  const dialogRefStub = {
    afterClosed() {
      return of(true);
    }
  };

  const dialogStub = { open: () => dialogRefStub };

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [],
      declarations: [ MyComponent ],
      providers: [
        { provide: MatDialog,  useValue: dialogStub }
      ]
    })
      .compileComponents();
  }));
  //...
});

Algunos enlaces que probé:

  • Diálogo de material angular simulado afterClosed () para prueba unitaria
  • ¿Cómo escribo una prueba simple para verificar el comportamiento de MatDialog en Angular 2?
  • No se puede leer la propiedad ‘afterClosed’ de undefined cuando la unidad prueba MatDialog en Jasmine
  • Fallido: no se pueden resolver todos los parámetros para MatDialogRef: (?,?,?). prueba unitaria proyecto Angular
  • ¿Cómo hago una prueba unitaria de que MatDialog está cerrado, por mat-dialog-close o de otra manera?

Puedes cortar el Dialog y es DialogRef valor de retorno.

Hago:

  const dialogRefStub = {
    afterClosed() {
      return of('result'); // this can be whatever, esp handy if you actually care about the value returned
    }
  };

  const dialogStub = { open: () => dialogRefStub };

Y luego agrego a los proveedores:

  {
    provide: MatDialog,
    useValue: dialogStub
  }
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *