Как смоделировать ввод с типом MatSidenav, в Angular 7 - PullRequest
0 голосов
/ 22 апреля 2019

Можно ли издеваться над МатСиденав?

Я хочу провести модульное тестирование компонента, который имеет в качестве входных данных MatSidenav из родительского компонента.

Пока я получаю эти ошибки в окне кармы:

Ошибка № 1:

ChildComponent> должен создать Ошибка типа: не удалось прочитать свойство 'runOutsideAngular' с нулевым значением

Ошибка № 2:

ChildComponent> при смене сиденав должно работать Ошибка типа: не удалось прочитать свойство 'runOutsideAngular' с нулевым значением

Я понимаю, что ошибка в том, что я высмеиваю суперкласс с нулевыми параметрами, может кто-нибудь показать мне лучшее решение по этому вопросу?

Мой код выглядит следующим образом.

родитель-component.html


<mat-sidenav-container>

  <mat-sidenav #filtersSidenav mode="side" opened="true" position="end"></mat-sidenav>

  <mat-sidenav-content>
    <app-child-component [sidenav]="filtersSidenav"></app-child-component >
  </mat-sidenav-content>

</mat-sidenav-container>

приложение-ребенок-component.ts

import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';

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

  @Input() sidenav: MatSidenav;

  constructor() { }

  ngOnInit() {
    if (this.sidenav) {
      this.sidenav.openedChange.subscribe( res => {
        console.log('works');
      });
    }
  }

}

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MatSidenav } from '@angular/material';
import { of, Observable } from 'rxjs';

// Modules
import { MaterialModule } from '@app-global-modules/material.module.ts';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterTestingModule } from '@angular/router/testing';

// Components
import { ChildComponent } from './child-component.component';

// Other
import { EventEmitter } from '@angular/core';


class SidenavMock extends MatSidenav {

  openedChange: EventEmitter<boolean> = new EventEmitter<boolean>(true);

  constructor() {
    super(null, null, null, null, null, null);
  }

}


describe('ChildComponent', () => {

  let component: ChildComponent;
  let fixture: ComponentFixture<ChildComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        MaterialModule,
        ReactiveFormsModule,
        HttpClientModule,
        RouterTestingModule
      ],
      declarations: [
        ChildComponent,
      ]
    })
    .compileComponents();
  }));


  beforeEach(async() => {
    fixture = TestBed.createComponent(ChildComponent);
    component = fixture.componentInstance;


    component.sidenav = new SidenavMock(); // <== I mock

    component.ngOnInit();
    await fixture.whenStable();
    fixture.detectChanges();
  });


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


  fit('on sidenav change should work', () => {
    const consoleLogSpy = spyOn(console, 'log').and.callThrough();
    component.sidenav.toggle();

    expect(consoleLogSpy).toHaveBeenCalledWith('works');
  });


});


1 Ответ

0 голосов
/ 23 апреля 2019

Можете ли вы попробовать:

@Component({
    selector: 'testing-component',
    template: `
        <mat-sidenav-container>

        <mat-sidenav #filtersSidenav mode="side" opened="true" position="end"></mat-sidenav>

        <mat-sidenav-content>
            <app-child-component [sidenav]="filtersSidenav"></app-child-component >
        </mat-sidenav-content>

        </mat-sidenav-container>
    `
})
class TestBedComponent {
    @ViewChild(ChildComponent) public componentUnderTest: ChildComponent ;    
    constructor() {}
}

В файле спецификации:

// Components
import { ChildComponent } from './child-component.component';
// Other
import { EventEmitter } from '@angular/core';


describe('ChildComponent', () => {

  let component: TestBedComponent;
  let fixture: ComponentFixture<TestBedComponent>;
  let childComponent: ChildComponent;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        MaterialModule,
        ReactiveFormsModule,
        HttpClientModule,
        RouterTestingModule
      ],
      declarations: [
        ChildComponent,TestBedComponent
      ]
    })
    .compileComponents();
  }));


  beforeEach(async() => {
    fixture = TestBed.createComponent(TestBedComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
    childComponent = component.componentUnderTest;
  });


  fit('should create', () => {
    expect(childComponent).toBeTruthy();
  });
});

Этот способ тестирования часто предпочтителен, когда есть некоторые тесно связанные данные, которые требуются дочернему компоненту (как я вижу в вашем случае).

Вы можете продолжить тестирование childComponent таким же образом, как и при component в файле спецификации.

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