如何在Angular 7中使用MatSidenav类型模拟输入

问题描述 投票:0回答:1

有可能嘲笑MatSidenav?

我想对从父组件输入MatSidenav作为输入的组件进行单元测试。

到目前为止,我在karma窗口中得到了这个错误:

错误#1:

ChildComponent>应该创建TypeError:无法读取null的属性'runOutsideAngular'

错误#2:

ChildComponent> on sidenav change应该工作TypeError:无法读取null的属性'runOutsideAngular'

我理解错误是因为我用null参数模拟超类,有人能告诉我一个更好的解决方案吗?

我的代码看起来像这样。

家长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>

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


});


angular angular-material karma-jasmine
1个回答
0
投票

你可以尝试:

@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() {}
}

在spec文件中:

// 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

© www.soinside.com 2019 - 2024. All rights reserved.