Angular单元测试spyOn报错open()不存在 如何不用spyOn测试弹窗?
Angular 弹窗单元测试问题解决方案
问题1:spyOn(component.dialog, 'open')报错原因及修复
错误根源
- 你在providers中给
MatDialog配置的是useValue: {},注入到组件的dialog实例是空对象,不存在open方法,直接触发spy报错 - 你定义的带
open方法的mockDialogRef放错了配置位置,被误写到了MatDialogRef的provider参数中,没有绑定给MatDialog - 两处重复调用
TestBed.configureTestingModule导致配置冲突,是偶尔提示spy已被使用的核心诱因
修复步骤
- 删掉第一个没有实际作用的
beforeEach配置块,避免配置冲突 - 修正providers配置:
// 原错误配置 { provide: MatDialog, useValue: {} }, { provide: MatDialogRef, useValue: dialogRefServiceSpy, mockDialogRef }, // 修正后配置 { provide: MatDialog, useValue: mockDialogRef // 将带open方法的mock对象绑定给MatDialog }, { provide: MatDialogRef, useValue: dialogRefServiceSpy },
- 修正测试用例(注意你原测试用例中期望打开的
ParamGameComponent和实际代码中打开的MultiComponent不一致,需要对应修正):
fit('openMulti test', () => { const expectedConfig = new MatDialogConfig(); expectedConfig.disableClose = true; expectedConfig.autoFocus = true; component.openMulti(); // 直接用mock里的spy即可,无需重复spyOn expect(mockDialogRef.open).toHaveBeenCalledWith(MultiComponent, expectedConfig); });
问题2:不使用spyOn完成弹窗测试的方法
可以实现,常用两种方案:
- 使用Angular Material官方提供的
MatDialogHarness配合HarnessLoader进行测试,直接验证弹窗是否弹出、弹窗配置、弹窗内容是否符合预期,属于集成测试写法 - 不mock
MatDialog,导入完整MatDialogModule并挂载真实弹窗容器,调用打开方法后直接查询DOM判断对应弹窗组件是否存在,验证参数配置
以上非spy方案属于集成测试范畴,执行速度比单元测试spy方案慢,纯单元测试场景优先使用spy方案。
内容的提问来源于stack exchange,提问作者Mohamed Sameh Sellami
相关产品推荐
相关产品推荐

