angular - Không thể đọc thuộc tính 'afterClosed' của undefined khi kiểm thử đơn vị MatDialog trong Jasmine
Tôi nhận được lỗi sau từ Karma Jasmine:
TypeError: Không thể đọc thuộc tính 'afterClosed' của undefined
Tôi đã tìm kiếm một cách chân thành, nhưng tôi không thể tìm thấy giải pháp trên Stack Overflow hoặc trong các nguồn khác.
Đây là cách tôi mở MatDialog trong component của mình:
(Như đã được tài liệu hóa)
constructor(public dialog: MatDialog) {}
public openDialog(): void {
const dialogReference: MatDialogRef<any, any> = this.dialog.open(myDialogComponent, {
width: '1728px'
});
dialogReference.afterClosed().subscribe((result) => {
});
}
Đây là cấu hình kiểm thử đơn vị của tôi:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
myRequestComponent
],
imports: [
MatDialogModule,
ReactiveFormsModule
],
providers: [
{ provide: MatDialog, useValue: {} },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(myRequestComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
Đây là bài kiểm tra đơn vị của tôi:
it('openDialog() should open a dialog', () => {
spyOn(component.dialog, 'open');
component.openDialog();
expect(component.dialog.open).toHaveBeenCalled();
});
Tôi có phải giả lập MatDialog hay MatDialogReference không?
Câu trả lời #1
Hãy phân tích vấn đề của bạn từng bước một.
Đầu tiên, bằng cách đăng ký
providers: [{ provide: MatDialog, useValue: {} }],
Bảng thử nghiệm của bạn sẽ chèn một đối tượng không có hành vi (ví dụ: phương thức/thành viên thể hiện) bất cứ khi nào MatDialog cần được giải quyết.
Điều này thực sự không cần thiết, vì bạn đang nhập MatDialogModule vào test bed của mình, vì vậy một thể hiện của MatDialog có thể được giải quyết mà không gặp vấn đề gì. Nhưng hãy giữ theo cách của bạn. Giải pháp này sẽ yêu cầu bạn loại bỏ dòng đó.
Thứ hai, bằng cách thực hiện:
spyOn(component.dialog, 'open')
bạn đang cài đặt một proxy cho phương thức instance open trong đối tượng được tham chiếu bởi component.dialog. Trong trường hợp này, là đối tượng rỗng mà bạn đã đăng ký trước đó.
Mặc dù thực tế đối tượng không có thành viên như vậy, jasmine sẽ tự động thêm proxy vào vị trí của nó. Đó là lý do tại sao bạn không thấy lỗi như this.dialog.open is not a function.
Cuối cùng, bất cứ khi nào có tương tác, proxy sẽ ghi lại thông tin về các tương tác đó và chuyển hướng các lần gọi đến thành viên open gốc. Vì không có triển khai gốc, một hàm không trả về sẽ được sử dụng thay thế, và cuối cùng sẽ kích hoạt accessing foo of undefined.
Tóm tắt ngắn gọn;
Loại bỏ { provide: MatDialog, useValue: {} } và sử dụng những thứ sau để giả lập phiên bản MatDialogRef cần thiết:
import { EMPTY} from 'rxjs';
it('openDialog() should open a dialog', () => {
const openDialogSpy = spyOn(component.dialog, 'open')
.and
.returnValue({afterClosed: () => EMPTY});
component.openDialog();
expect(openDialogSpy).toHaveBeenCalled();
});
