dialogRef.afterClosed не является функцией - PullRequest
0 голосов
/ 24 октября 2018

Привет, я провожу юнит-тестирование и пытаюсь получить покрытие для моей подписки.Однако он продолжает работать с ошибкой dialogRef.afterClosed не является функцией

Я не уверен в том, что или как я могу следить за функцией afterClosed (), но это единственная часть, которую я не могукажется, чтобы покрыть....

import { MatDialog } from '@angular/material/dialog';
....
constructor( private dialog: MatDialog) { }

showLogin(): void {

  const dialogRef = this.dialog.open(LoginDialogComponent, {
    width: '400px',
    height: 'auto',
    data: this.loginContext
  });

  dialogRef.afterClosed().subscribe(result => {
    if (this.loginContext.loggedIn) {
      this.showApply();
    }
  });
}

это LoginDialogComponent

 ....

 @Component({
   selector: 'app-login-dialog',
   templateUrl: './login-dialog.component.html',
   styleUrls: ['./login-dialog.component.scss']
 })
 export class LoginDialogComponent implements OnInit {

   constructor(
     private authService: AuthService,
     private alertService: AlertService,
     public dialogRef: MatDialogRef<LoginState>,
     @Inject(MAT_DIALOG_DATA) public data: LoginState) { }

   ngOnInit() {
     this.data.loggedIn = false;
   }

   login(loginEvent: LoginEvent): void {


     this.authService.login(loginData).then(
       resp => {
         this.data.loggedIn = true; // feedback
         this.dialogRef.close();
       },
       err => {
         this.alertService.showAlert(err);
       }
     );
   }

 }

Ответы [ 2 ]

0 голосов
/ 31 мая 2019

Я взял ответ Сэма Цая на шаг вперед и создал более короткий файл-заглушку.Вот содержимое файла заглушки:

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

Затем в файле .spec.ts вы используете заглушку следующим образом:

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

И в реальном тесте вы можете установить возвращаемое значениев true или false для имитации нажатия кнопки «ОК» или «Отмена» соответственно путем вызова функции setResult ():

dialogStub.setResult(true); 

или

dialogStub.setResult(false);

Примечание: значение по умолчанию длязаглушка проверяет «ОК», поэтому вам не нужно вызывать функцию, если вы просто проверяете «ОК».

Приведенные ниже тесты сначала имитируют «Отмена», а затем нажатие кнопки «ОК»:

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

Первоначальный ответ

Я искал везде краткий способ издеваться над MatDialog и избавиться от получаемой мной ошибки dialogRef.afterClosed не является функцией .(см. некоторые ссылки, которые я пробовал внизу).Ничто из того, что я нашел, не было правильным решением, пока я не попробовал ответ Сэма Цая на этот вопрос.Это было простое решение, которое избавило меня от всех моих ошибок и позволило мне правильно протестировать свое приложение.Хотел бы я найти это, прежде чем тратить столько времени на все остальные ссылки.

Это модульный тест, который не прошел;это событие не удалось выполнить ('button'). click, поскольку оно открывает MatDialog и выполняет удаление только в том случае, если диалоговое окно возвращает true.Я не знал, как правильно смоделировать MatDialog, чтобы могло произойти удаление:

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

Я исправил это, добавив следующее:

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

Некоторые ссылки, которые я пробовал:

0 голосов
/ 18 декабря 2018

Вы можете заглушить Dialog и его DialogRef возвращаемое значение.

Я делаю:

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

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

И затем я добавляю к провайдерам:

  {
    provide: MatDialog,
    useValue: dialogStub
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...