您如何存根/模拟作为ViewChild读取的指令/组件?
例如,使用简单的指令从angular.io:
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor() { }
}
假设我正在测试AppComponent
,并使用HighlightDirective
来读取ViewChild
:
@ViewChild(HighlightDirective) theHighlightDirective: HighlightDirective
和废止指令是:
@Directive({
selector: '[appHighlight]'
})
export class StubbedHighlightDirective {
constructor() { }
}
由于组件试图读取HighlightDirective
,所以即使您在单元测试中声明了StubbedHighlightDirective
,theHighlightDirective
也是不确定的。
示例:
it('HighlightDirective is defined', () => {
// This test fails
expect(component.theHighlightDirective).toBeDefined();
});
如果您忽略tslint中的某些内容或使用as
关键字,则可以解决此问题:
Version 1: Just ignore some things in tslint so compiler doesn't complain
it('HighlightDirective is defined', () => {
// Compiler will typically complain saying that
// StubbedHighlightDirective isn't assignable to type of HighlightDirective
component.theHighlightDirective = new StubbedHighlightDirective();
// this passes
expect(component.theHighlightDirective).toBeDefined();
});
Version 2: Use "as" keyword
it('HighlightDirective is defined', () => {
// Actually compiler will still complain with warnings
component.theHighlightDirective = new StubbedHighlightDirective() as HighlightDirective;
// this passes
expect(component.theHighlightDirective).toBeDefined();
});
还有另一种方法可以干净地存根这些ViewChild引用吗?
答案 0 :(得分:1)
问题是您正在使用一个类来查找子级,并且该类已被存根替换。您可以在指令(docs,blog post)中使用匹配的exportAs
链接,以确保真实版本和存根具有相同的名称。
在原始指令装饰器中:
@Directive({
selector: '[appHighlight]',
exportAs: 'appHighlight'
})
export class HighlightDirective {
在存根指令中:
@Directive({
selector: '[appHighlight]',
exportAs: 'appHighlight'
})
export class StubbedHighlightDirective {
然后在使用指令的模板中:
<div appHighlight #appHighlight="appHighlight">
完成所有这些操作后,您需要更新@ViewChild
定义以使用字符串而不是类:
@ViewChild('appHighlight') theHighlightDirective: HighlightDirective