有可能嘲笑MatSidenav?
我想对从父组件输入MatSidenav作为输入的组件进行单元测试。
到目前为止,我在karma窗口中得到了这个错误:
错误#1:
ChildComponent>应该创建TypeError:无法读取null的属性'runOutsideAngular'
错误#2:
ChildComponent> on sidenav change应该工作TypeError:无法读取null的属性'runOutsideAngular'
我理解错误是因为我用null参数模拟超类,有人能告诉我一个更好的解决方案吗?
我的代码看起来像这样。
<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');
});
});
你可以尝试:
@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
。