TypeError:无法在 Angular Material 对话框测试中读取未定义的属性(读取“push”)

问题描述 投票:0回答:1

此问题之前的答案并不能解决我的问题。

我在 Angular 组件中测试打开删除用户对话框的方法时遇到 TypeError。错误消息指出:

TypeError:无法读取未定义的属性(读取“push”) 在 MatDialog.open (node_modules/@angular/material/fesm2022/dialog.mjs:598:26) 在 MatDialog.open (node_modules/@angular/material/fesm2022/dialog.mjs:598:26) 在 UserComponent.deleteUser (src/app/components/user/user.component.ts:108:35) 在 UserContext.apply (src/app/components/user/user.component.spec.ts:147:15) 在 _ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:369:28) 在 ProxyZoneSpec.onInvoke (node_modules/zone.js/fesm2015/zone-testing.js:2081:39) 在 _ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:368:34) 在 ZoneImpl.run (node_modules/zone.js/fesm2015/zone.js:111:43) 在 runInTestZone (node_modules/zone.js/fesm2015/zone-testing.js:216:38) 在用户上下文中。 (node_modules/zone.js/fesm2015/zone-testing.js:234:32) 在 在 UserContext.apply (src/app/components/user/user.component.spec.ts:147:15) 在 _ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:369:28) 在 ProxyZoneSpec.onInvoke (node_modules/zone.js/fesm2015/zone-testing.js:2081:39) 在 _ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:368:34) 在 ZoneImpl.run (node_modules/zone.js/fesm2015/zone.js:111:43) 在 runInTestZone (node_modules/zone.js/fesm2015/zone-testing.js:216:38)

这是我的 UserComponent 的相关部分:

deleteUser(userId: number, userNickname: string): void {
  const dialogRef = this.dialog.open(DeleteDialogComponent, {
    height: '400px',
    width: '550px',
    data: { userId, userNickname },
  });

  dialogRef.afterClosed().subscribe(result => {
    if (result) {
      const subscription = this.userService.deleteUser(userId).subscribe({
        next: () => {
          console.log("Ok!")
        },
        error: error => {
        }
      });
    }
  });
}

这是我的测试设置:

describe('UserComponent', () => {
  let component: UserComponent;
  let fixture: ComponentFixture<UserComponent>;
  let userServiceMock: jasmine.SpyObj<UserService>;
  let routerMock: jasmine.SpyObj<Router>;
  let dialogSpy: jasmine.SpyObj<MatDialog>;

  beforeEach(async () => {
    userServiceMock = jasmine.createSpyObj<UserService>('UserService', {
      deleteUser: of(1)
    });
    routerMock = jasmine.createSpyObj<Router>('Router', ['navigate']);
    dialogSpy = jasmine.createSpyObj('MatDialog', ['open']);

    await TestBed.configureTestingModule({
      imports: [UserComponent, MatDialogModule, BrowserAnimationsModule],
      providers: [
        { provide: UserService, useValue: userServiceMock },
        { provide: Router, useValue: routerMock },
        { provide: MatDialog, useValue: dialogSpy }
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(UserComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should open modal and delete user', () => {
    const userId = 1;
    const userNickname = 'JohnSmith';

    component.deleteUser(userId, userNickname);

    const dialogRef = dialogSpy.open.calls.mostRecent().returnValue;
    dialogRef.afterClosed = jasmine.createSpy().and.returnValue(of(true));

    component.deleteUser(userId, userNickname);
    
    expect(userServiceMock.deleteUser).toHaveBeenCalledWith(userId);
  });
});

行 this.openDialogs.push(dialogRef);在 MatDialog 实现中似乎是问题的根源。

我怀疑在测试过程中没有正确创建dialogRef,但我不确定如何解决这个问题。

如何确保正确模拟dialogRef,以便openDialogs数组不是未定义的? 我需要对测试设置或 deleteUser 方法进行任何调整才能避免此错误吗? 任何见解或建议将不胜感激!

angular testing jasmine dialog
1个回答
0
投票

看看你的测试,你在嘲笑整个

MatDialog
。 这可能会导致问题,因为您在测试中使用的间谍对象缺少真正的 MatDialog 具有的内部属性和方法。

你可以做的就是监视

MatDialog.open
(和
afterClosed

代码片段:

it('should open modal and delete user', () => {
    const userId = 1;
    const userNickname = 'JohnSmith';

    const matDialogRefSpy = jasmine.createSpyObj<MatDialogRef<DeleteDialogComponent>>(
      'MatDialogRef',
      ['afterClosed']
    );
    matDialogRefSpy.afterClosed.and.returnValue(of(true));

    // Spy on the open method of MatDialog to return the mock MatDialogRef
    spyOn(component.dialog, 'open').and.returnValue(matDialogRefSpy);

    component.deleteUser(userId, userNickname);

    expect(userServiceMock.deleteUser).toHaveBeenCalledWith(userId);
});

© www.soinside.com 2019 - 2024. All rights reserved.