如何测试组件构造函数中调用的MatDialog.open方法?
如何测试组件构造函数中调用的MatDialog.open方法?
我太懂你这个困扰了——构造函数里的代码在组件一实例化就立刻跑起来了,等你后面再去加spy,早就错过调用时机了,自然抓不到记录。咱们来调整下测试代码,把顺序理顺:
核心思路:提前准备好Spy,再实例化组件
关键是要在组件构造函数执行之前,就把MatDialog.open的spy设置好,这样构造函数里的调用才会被捕获到。
修改后的完整测试代码
import { ElementRef } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { AppComponent } from './app.component'; import { MediaService } from './services/media.service'; import { WelcomeComponent } from './welcome/welcome.component'; describe('AppComponent', () => { let component: AppComponent; let fixture: ComponentFixture<AppComponent>; // 提前声明dialog的spy,方便后续使用 let dialogOpenSpy: jest.SpyInstance; beforeEach(async () => { await TestBed.configureTestingModule({ imports: [AppComponent, NoopAnimationsModule, MatDialogModule], providers: [ { provide: ElementRef, useValue: {} }, { provide: MediaService, useValue: {} }, // 这里不需要单独provide MatDialog,MatDialogModule已经提供了实例 ] }).compileComponents(); // 第一步:先获取MatDialog实例,提前创建open方法的spy const dialog = TestBed.inject(MatDialog); dialogOpenSpy = jest.spyOn(dialog, 'open').mockImplementation(() => ({ // 返回模拟的DialogRef,避免测试时因缺少方法报错 afterClosed: () => Promise.resolve(null) })); // 第二步:再创建组件实例,此时构造函数执行,dialog.open的调用会被spy捕获 fixture = TestBed.createComponent(AppComponent); component = fixture.componentInstance; // Angular 14+独立组件中,createComponent已触发初始化,无需额外调用detectChanges }); it('应该在组件初始化时打开欢迎对话框', () => { // 不需要手动调用dialog.open!构造函数已经自动执行了 expect(dialogOpenSpy).toHaveBeenCalled(); // 还可以验证调用参数是否符合预期 expect(dialogOpenSpy).toHaveBeenCalledWith(WelcomeComponent, { width: '350px', height: '350px' }); }); });
为什么原来的测试没效果?
你之前的代码里,fixture.createComponent()和fixture.detectChanges()已经触发了组件构造函数,执行了dialog.open操作,之后再去spyOn(component.dialog, 'open'),此时spy是在调用发生后才创建的,自然捕获不到之前的调用记录。
额外注意点
- 给spy加上
mockImplementation是为了返回符合DialogRef类型的对象,避免测试时因缺少必要方法而报错; - 由于组件用
inject()获取MatDialog,TestBed.inject拿到的实例和组件内的是同一个,所以spy能正常生效;
备注:内容来源于stack exchange,提问作者JSmith
相关产品推荐
相关产品推荐

