Я пишу модульный тест для метода ngAfterViewInit в коде моего компонента для покрытия. Я использую жасминовую карму в качестве своего инструмента тестирования. На данный момент покрытие кода жалуется, что this.closeModal (), который называется частью подписки, не покрывается.
По сути, я передаю ссылку childcomponent на родительский компонент. Как видите, дочерний компонент имеет выходное событие с именем closeModal. Родительский компонент подписывается на него. Я сделал следующее в моем тесте, как вы можете видеть в коде ниже. Это связывает выходное событие closeModal с родительским компонентом и пытается создать событие через дочерний компонент. Это не похоже на работу. Есть ли проблема с тем, как я связываюсь?
component.ngAfterViewInit();
component.closeModal.bind(childComponent.closeModal);
component.componentRef.instance.closeModal.subscribe(() => {
tick();
childComponent.closeModal.emit(true);
expect(component.closeModal).toHaveBeenCalled();
Родительский компонент
export class ModalDialogComponent implements AfterViewInit, OnDestroy {
private readonly _onClose = new Subject<any>();
public componentRef: ComponentRef<any>;
public childComponentType: Type<any>;
public onClose = this._onClose.asObservable();
// add this:
@ViewChild(InsertionDirective, { static: false })
insertionPoint: InsertionDirective;
constructor(public componentFactoryResolver: ComponentFactoryResolver,
public cd: ChangeDetectorRef,
public dialog: ModalDialogRef) {
}
ngAfterViewInit() {
this.loadChildComponent(this.childComponentType);
this.cd.detectChanges();
}
loadChildComponent(componentType: Type<any>) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentType);
const viewContainerRef = this.insertionPoint.viewContainerRef;
viewContainerRef.clear();
this.componentRef = viewContainerRef.createComponent(componentFactory);
this.componentRef.instance.closeModal.subscribe(() => this.closeModal());
}
closeModal() {
this.dialog.close();
}
}
Дочерний компонент
@Component({
selector: 'app-example',
templateUrl: './example.component.html'
})
export class ExampleComponent {
@Output() closeModal = new EventEmitter<boolean>();
constructor(public config: ModalDialogConfig,
public dialog: ModalDialogRef
) {}
onCancel() {
this.dialog.close('user clicked cancel');
}
onOk() {
this.dialog.close('User clicked ok');
}
}
Тест
fdescribe('ModalDialogComponent', () => {
let component: ModalDialogComponent;
let childComponent: ExampleComponent;
let fixture: ComponentFixture<ModalDialogComponent>;
let childFixture: ComponentFixture<ExampleComponent>;
let mockMouseEvent;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [SharedModule, ModalDialogModule, NgxsModule.forRoot([])],
providers: [ModalDialogConfig, ModalDialogRef ]
})
.overrideModule(BrowserDynamicTestingModule, { set: { entryComponents: [ModalDialogComponent, ExampleComponent] } })
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ModalDialogComponent);
childFixture = TestBed.createComponent(ExampleComponent);
mockMouseEvent = new Mock<MouseEvent>({ stopPropagation: () => Promise.resolve(true) });
component = fixture.componentInstance;
childComponent = childFixture.componentInstance;
component.childComponentType = ExampleComponent;
component.componentRef = childFixture.componentRef;
spyOn(component.componentRef.instance, 'closeModal').and.returnValue(Observable.of(true));
fixture.detectChanges();
});
it('should call ngAfterViewInit ', () => {
component.ngAfterViewInit();
component.closeModal.bind(childComponent.closeModal);
component.componentRef.instance.closeModal.subscribe(() => {
tick();
childComponent.closeModal.emit(true);
expect(component.closeModal).toHaveBeenCalled();
});
});