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

单元测试报错:Cannot read property 'open' of undefined 问题求助

Angular单元测试报错:Cannot read property 'open' of undefined 解决方法

组件代码

openUpdate(rowSelected: iData) {
        let dialogRef = this.dialog.open(DialogEditComponent, {});
        dialogRef.componentInstance.dialogRef = dialogRef;
        dialogRef.componentInstance.selectedData = rowSelected;
        const sub = dialogRef.componentInstance.onAdd.subscribe((data: iData) => {
            if (data) {
                this.update(data);
            }
        });
        dialogRef.afterClosed().subscribe(() => {
            sub.unsubscribe();
        });
    }

测试代码(spec.ts)

beforeEach(async () => {
    const dialogSpy = {
      open: jasmine.createSpy('open').and.returnValue({
        componentInstance: {
          onAdd: jasmine.createSpyObj('onAdd', ['subscribe'])
        },
        afterClosed: () => {
          return jasmine.createSpyObj('afterClosed', ['subscribe']);
        }
      })
    };
    toastrServiceSpy = jasmine.createSpyObj('ToastrService', ['success', 'error']);

    await TestBed.configureTestingModule({
      declarations: [Component1, DialogEditComponent],
      imports: [MatDialogModule, BrowserAnimationsModule],
      providers: [
        { provide: MatDialog, useValue: dialogSpy },
        { provide: ToastrService, useValue: toastrServiceSpy },
        { provide: MAT_DIALOG_DATA, useValue: {} },
      ],
    }).compileComponents();
  });

// ...

it('should open the edit dialog with the selected data', async () => {
    await component.openUpdate(mockData[0]);
    expect(dialogSpy.open).toHaveBeenCalled();
  });

错误信息

TypeError: Cannot read property 'open' of undefined
        at UserContext.<anonymous> (src/app/features/component1.component.spec.ts:99:22)
        at Generator.next (<anonymous>)
        at asyncGeneratorStep (node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:3:1)
        at apply (node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:22:1)
        at _ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:409:30)
        at ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/zone-testing.js:303:43)
        at _ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:408:56)
        at Zone.run (node_modules/zone.js/dist/zone.js:169:47)
        at apply (node_modules/zone.js/dist/zone.js:1326:38)
        at _ZoneDelegate.invokeTask (node_modules/zone.js/dist/zone.js:443:35)

问题根源

dialogSpy是beforeEach函数内部的局部变量,测试用例(it块)不在它的作用域范围内,所以当你在it块里调用expect(dialogSpy.open)时,dialogSpy是undefined,直接触发报错。另外,你还漏了在beforeEach里实例化组件并触发变更检测,可能会影响依赖注入的完成。

修复方案

把dialogSpy提升为测试文件的顶层变量,同时完善组件实例化流程:

// 把变量提到顶层,让所有测试用例都能访问
let dialogSpy: any;
let toastrServiceSpy: any;
let component: Component1;
let fixture: ComponentFixture<Component1>;

beforeEach(async () => {
  dialogSpy = {
    open: jasmine.createSpy('open').and.returnValue({
      componentInstance: {
        onAdd: jasmine.createSpyObj('onAdd', ['subscribe']),
        // 提前定义组件实例里用到的属性,避免后续潜在报错
        dialogRef: null,
        selectedData: null
      },
      afterClosed: () => jasmine.createSpyObj('afterClosed', ['subscribe'])
    })
  };
  toastrServiceSpy = jasmine.createSpyObj('ToastrService', ['success', 'error']);

  await TestBed.configureTestingModule({
    declarations: [Component1, DialogEditComponent],
    imports: [MatDialogModule, BrowserAnimationsModule],
    providers: [
      { provide: MatDialog, useValue: dialogSpy },
      { provide: ToastrService, useValue: toastrServiceSpy },
      { provide: MAT_DIALOG_DATA, useValue: {} },
    ],
  }).compileComponents();

  // 实例化组件并触发变更检测,确保依赖注入完成
  fixture = TestBed.createComponent(Component1);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

it('should open the edit dialog with the selected data', async () => {
  await component.openUpdate(mockData[0]);
  expect(dialogSpy.open).toHaveBeenCalled();
});

修改后,dialogSpy在it块里就能正常访问,同时组件的this.dialog也能正确注入Spy对象,测试就能正常运行了。

内容的提问来源于stack exchange,提问作者Kenzo_Gilead

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 07:32:05