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

Angular通用对话框关闭功能单元测试报错排查求助

解决DialogService单元测试中genericDialogClosed方法的报错问题

报错原因

直接调用genericDialogClosed()时,service.genericDialogRef未被初始化——这个属性仅在调用openGenericDialog()后才会被赋值,触发了方法内的错误抛出逻辑:Dialog ref wasn't initialized! Call open first。


方案1:模拟完整调用流程(推荐,贴合实际业务逻辑)

通过完善MatDialog的mock,让open方法返回带有afterClosed的mock对象,先调用openGenericDialog初始化ref,再测试genericDialogClosed:

describe('DialogService', () => {
  let service: DialogService;
  let matDialogMock = jasmine.createSpyObj(['open']);
  let toastrServiceMock = {};
  let translateService: TranslateService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [TranslateModule.forRoot()],
      providers: [
        { provide: MatDialog, useValue: matDialogMock },
        { provide: ToastrService, useValue: toastrServiceMock },
      ],
    });
    service = TestBed.inject(DialogService);
    translateService = TestBed.inject(TranslateService);
    // 重置mock状态
    matDialogMock.open.calls.reset();
  });

  // ... 其他测试用例

  it('should return observable from dialog afterClosed when genericDialogClosed is called', fakeAsync(() => {
    // 1. 构建Mock的MatDialogRef,模拟afterClosed返回可观察对象
    const dialogRefMock = jasmine.createSpyObj('MatDialogRef', ['afterClosed']);
    dialogRefMock.afterClosed.and.returnValue(of(true));
    // 让MatDialog的open方法返回这个Mock
    matDialogMock.open.and.returnValue(dialogRefMock);

    // 2. 调用openGenericDialog初始化genericDialogRef
    service.openGenericDialog({ title: 'test', content: 'test content' }); // 传入符合GenericDialogOptions的参数

    // 3. 订阅并验证结果
    let dialogResult: boolean | undefined;
    service.genericDialogClosed().subscribe(res => {
      dialogResult = res;
    });

    tick();

    expect(dialogResult).toBe(true);
    expect(dialogRefMock.afterClosed).toHaveBeenCalled();
    expect(service.genericDialogRef).toBe(dialogRefMock);
  }));

  // 补充测试:验证未调用open时抛出错误
  it('should throw error if genericDialogClosed is called before openGenericDialog', () => {
    expect(() => service.genericDialogClosed()).toThrowError("Dialog ref wasn't initialized! Call open first");
  });
});

方案2:手动初始化genericDialogRef(快速验证)

直接给service.genericDialogRef赋值mock对象,适用于单独验证方法逻辑:

it('should return observable when genericDialogRef is initialized', () => {
  // 构建带有afterClosed的mock ref
  const mockAfterClosed$ = of(false);
  service.genericDialogRef = {
    afterClosed: jasmine.createSpy().and.returnValue(mockAfterClosed$)
  } as MatDialogRef<GenericDialogComponent>;

  let result: boolean | undefined;
  service.genericDialogClosed().subscribe(res => {
    result = res;
  });

  expect(result).toBe(false);
  expect(service.genericDialogRef?.afterClosed).toHaveBeenCalled();
});

内容的提问来源于stack exchange,提问作者N.Selwi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:24:32