角的单元测试 - 磕碰/嘲笑一个指令与ViewChild参考

时间:2019-01-31 20:08:07

标签: angular unit-testing jasmine viewchild

您如何存根/模拟作为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,所以即使您在单元测试中声明了StubbedHighlightDirectivetheHighlightDirective也是不确定的。

示例:

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引用吗?

1 个答案:

答案 0 :(得分:1)

问题是您正在使用一个类来查找子级,并且该类已被存根替换。您可以在指令(docsblog 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