Jasmine spy未被调用的Angular单元测试问题求助
问题根因
你遇到的Expected spy open to have been called报错核心是spy绑定的实例和组件实际调用的MatDialog实例存在引用不一致的风险,且测试写法不符合Angular测试的最佳实践:
- 直接spy全局定义的mock对象,若测试过程中mock实例被重置/重新赋值,就会出现组件调用的对象和你spy的对象不是同一个的问题
- 没有从TestBed注入器中获取组件实际依赖的MatDialog实例来做spy,无法保证绑定对象的准确性
修正方案
建议直接从TestBed中拿到注入给组件的MatDialog实例创建spy,同时避免使用全局固定的mock对象,优化后的测试代码如下:
import { MatDialog } from '@angular/material/dialog'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentWithAButton } from './component-with-a-button.component'; describe('ComponentWithAButton', () => { let component: ComponentWithAButton; let fixture: ComponentFixture<ComponentWithAButton>; // 声明matDialog变量,用于存储注入的实例 let matDialog: jasmine.SpyObj<MatDialog>; beforeEach(async () => { // 每次测试前创建新的spy对象,避免用例间相互影响 const closeDialogSpy = jasmine.createSpyObj('MatDialog', ['open']); await TestBed.configureTestingModule({ declarations: [ComponentWithAButton], providers: [ { provide: MatDialog, useValue: closeDialogSpy, } ], }).compileComponents(); // 从TestBed注入器获取组件实际使用的MatDialog实例 matDialog = TestBed.inject(MatDialog) as jasmine.SpyObj<MatDialog>; }); beforeEach(() => { fixture = TestBed.createComponent(ComponentWithAButton); component = fixture.componentInstance; fixture.detectChanges(); }); describe('goBack', () => { it('should call closeDialog.open', () => { component.goBack(); // 直接断言注入实例的open方法被调用即可 expect(matDialog.open).toHaveBeenCalled(); }); }); });
其他注意点
如果你的测试是模拟真实按钮点击触发goBack,而不是直接调用组件方法,需要确保按钮点击事件绑定正确,且点击后调用了fixture.detectChanges()触发变更检测。
内容的提问来源于stack exchange,提问作者PaulBunion
相关产品推荐
相关产品推荐

