You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试组件构造函数中调用的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 07:19:51