angular - Angular 5 / Jasmine 单元测试 - 无法读取未定义的属性“componentInstance”
问题描述
我的单元测试有一个奇怪的错误,由于某种原因,我无法确定为什么会出现这个错误。你只有两个测试。一个是确保组件已创建,另一个是检查组件方法是否在调用时调用 Mat Dialog .open 方法......没什么太复杂的。这是我的代码...
describe('ClientDeactivateComponent', () => {
let component: ClientDeactivateComponent;
let fixture: ComponentFixture<ClientDeactivateComponent>;
const spyMatDialog = jasmine.createSpyObj('MatDialog', ['open']);
const spyRouter = jasmine.createSpyObj('Router', ['navigate']);
spyRouter.navigate.and.returnValue(Promise.resolve({}));
const spyClientsService = jasmine.createSpyObj('ClientsService', ['deactivateClient']);
const successDeativation = {};
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
ClientDeactivateComponent,
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
imports: [
HttpClientModule,
RouterTestingModule.withRoutes([{path: '**', component: ClientDeactivateComponent}])
],
providers: [
FormBuilder,
ClientsService
]
}).overrideComponent(ClientDeactivateComponent, {
set: {
providers: [
{provide: Router, useValue: spyRouter},
{provide: ClientsService, useValue: spyClientsService},
{provide: MatDialog, useValue: spyMatDialog},
{provide: Router, useValue: spyRouter},
{provide: ActivatedRoute, useValue: {params: from([{id: 1}])}}
],
template: '<div>Overridden template</div>'
}
}
)
.compileComponents();
}));
afterEach(() => {
spyMatDialog.open.calls.reset();
spyRouter.navigate.calls.reset();
spyClientsService.deactivateClient.calls.reset();
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(ClientDeactivateComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
describe('default', () => {
/* this works! */
it('should create', () => {
expect(component).toBeTruthy();
});
/* Why isn't this working? */
it('should open a modal window when confirmDeactivation is called', () => {
component.confirmDeactivation();
spyClientsService.deactivateClient.and.returnValue(successDeativation);
expect(spyMatDialog.open).toHaveBeenCalledWith(ConfirmDialogComponent);
});
});
});
第一个测试按预期通过,但第二个测试失败,出现以下错误:
TypeError:无法读取未定义的属性“componentInstance”
我在这里查看了很多答案,但我申请尝试解决这个问题的方法并没有奏效。我确信这与测试平台的加载方式有关,但我无法确定出了什么问题,为什么?
解决方案
我发现了问题。错误消息无法读取未定义的属性“componentInstance”使我专注于
component = fixture.componentInstance;
事实并非如此,我的模态模型 spyMatDialog 的模拟被错误地模拟了!下面的代码显示了如何正确模拟 spyMatDialog:
describe('ClientDeactivateComponent', () => {
let component: ClientDeactivateComponent;
let fixture: ComponentFixture<ClientDeactivateComponent>;
let spyDialogRef: any;
const spyRouter = jasmine.createSpyObj('Router', ['navigate']);
spyRouter.navigate.and.returnValue(Promise.resolve({}));
const spyClientsService = jasmine.createSpyObj('ClientsService', ['deactivateClient']);
spyClientsService.deactivateClient = () => of(true);
spyDialogRef = jasmine.createSpy();
spyDialogRef.componentInstance = {title: '', message: ''};
spyDialogRef.afterClosed = () => of(true);
const spyMatDialog = jasmine.createSpyObj('MatDialog', ['open']);
spyMatDialog.open.and.returnValue(spyDialogRef);
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
ClientDeactivateComponent,
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
imports: [
HttpClientModule,
RouterTestingModule.withRoutes([{path: '**', component: ClientDeactivateComponent}])
],
providers: [
FormBuilder,
ClientsService
]
}).overrideComponent(ClientDeactivateComponent, {
set: {
providers: [
{provide: Router, useValue: spyRouter},
{provide: ClientsService, useValue: spyClientsService},
{provide: MatDialog, useValue: spyMatDialog},
{provide: Router, useValue: spyRouter},
{provide: ActivatedRoute, useValue: {params: from([{id: 1}])}}
],
template: '<div>Overridden template</div>'
}
}
)
.compileComponents();
}));
afterEach(() => {
spyRouter.navigate.calls.reset();
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(ClientDeactivateComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
describe('default', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
it('should open a modal window when confirmDeactivation is called', () => {
component.confirmDeactivation();
expect(spyMatDialog.open).toHaveBeenCalled();
});
});
});
推荐阅读
- random - 不是真正随机的人工选择的伪随机变量?
- php - File could not be uploaded: missing temporary directory
- php - 在 Woocommerce 3 中以编程方式创建产品时设置产品类型
- c# - construct comma separated string from "name" property of objects stored in a list
- python - Dynamically resolve a pods address for get request
- html - 仅在 Edge 中使用 @font-face 定义的自定义字体
- python - Changing 3D scatter plot color based on specific column
- ruby-on-rails - 主动模型序列化器 each_serializer 与序列化器
- berkeley-db - berkeley-db-je 的最新版本是什么?
- php - PHP mysql数据未从最后一个ID检索