在Angular/Jasmine中测试扩展另外两个组件的组件



我有三个组件,它们相互扩展TileComponent->CollectionElementComponent->SelectableItemComponent。现在,我正在尝试使用Jasmine 3.4.0和Angular 8为TileComponent类编写一些单元测试。然而,测试(应该创建组件(失败了,因为模拟的selectableService没有正确地注入到扩展的扩展组件中:

Failed: Uncaught (in promise): TypeError: Cannot read property 'pipe' of undefined
TypeError: Cannot read property 'pipe' of undefined
at TileComponent.ngOnInit (http://localhost:9876/_karma_webpack_/src/app/shared/components/selectable/selectable-item.component.ts:26:14)
at TileComponent.ngOnInit (http://localhost:9876/_karma_webpack_/src/app/collection/view/elements/collection-element/collection-element.component.ts:32:15)
at TileComponent.ngOnInit (http://localhost:9876/_karma_webpack_/src/app/collection/view/elements/tile/tile.component.ts:65:15)

selectable-item.component.ts:26:14指的是此调用(另请参阅下面的代码片段(:this.selectableService.onDeselectAllSelectedItems.pipe(...)

我初始化测试组件如下:

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
TileComponent,
],
providers: [
{ provide: SelectableService, useClass: MockSelectableService },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(TileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it('should create component', () => {
expect(component).toBeTruthy();
});
});

...
@Injectable()
class MockSelectableService {
onDeselectAllSelectedItems = new EventEmitter<void>();
}

这种将服务注入组件的方式适用于其他组件测试,所以我不完全确定它为什么在这里失败。我已经尝试了几乎所有的东西,在两个父组件的声明中使用ng-mocksMockComponent(),尝试模拟两个父,并使用{ provide: ComponentName, useClass: MockComponentName}注入它们。还试图在beforeEach方法或CollectionElementComponent.prototype.ngOnInit = () => {}等中使用component.ngOnInit = () => {}重写ngOnInit方法。所有这些方法都会导致相同的错误。

受影响的组件如下所示:

export class SelectableItemComponent implements OnInit {
constructor(
public selectableService: SelectableService
) { }
ngOnInit() {
this.selectableService.onDeselectAllSelectedItems
.pipe(takeUntil(this.componentDestroyed$))
.subscribe(this.deselectItem.bind(this));
}
}

此类由CollectionElementComponent:扩展

export class CollectionElementComponent extends SelectableItemComponent implements OnInit {
constructor(
public selectableService: SelectableService,
) {
super(selectableService);
}
ngOnInit() {
super.ngOnInit();
// some other stuff
}
}

最后,TileComponent扩展了CollectionElementComponent

export class TileComponent extends CollectionElementComponent implements OnInit {
constructor(
public selectableService: SelectableService,
) {
super(selectableService);
}
ngOnInit() {
super.ngOnInit();
// some other stuff
}
}

非常感谢任何帮助或提示,因为我真的没有主意。。。感谢您的支持!

如果你使用ng mock,你也可以使用MockBuilder或MockProvider:

beforeEach(() => MockBuilder(
TileComponent,
[
CollectionElementComponent,
SelectableItemComponent,
SelectableService,
],
));
it('test', () => {
// mocking the prop of SelectableService 
const selectedItems$ = new EventEmitter();
MockInstance(
SelectableService,
'onDeselectAllSelectedItems',
selectedItems$,
);
const fixture = MockRender(TileComponent);
// should work properly now
});

最新更新