此问题之前的答案并不能解决我的问题。
我在 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 方法进行任何调整才能避免此错误吗? 任何见解或建议将不胜感激!
看看你的测试,你在嘲笑整个
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);
});