可以模拟MatSidenav吗?
我要对从父组件输入MatSidenav作为输入的组件进行单元测试。
到目前为止,我在业力窗口中收到此错误:
错误1:
ChildComponent>应该创建 TypeError:无法读取null的属性“ runOutsideAngular”
错误2:
ChildComponent>在sidenav更改上应该起作用 TypeError:无法读取null的属性“ runOutsideAngular”
我理解错误是因为我用空参数模拟了超类,有人可以向我展示一个更好的解决方案吗?
我的代码如下。
<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>
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');
});
});
答案 0 :(得分: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() {}
}
在规格文件中:
// 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
。