简体   繁体   English

Angular 单元测试 - 在 ViewChild 中使用引用存根/模拟指令

[英]Angular unit testing - stubbing/mocking a directive with reference in ViewChild

How do you stub/mock a directive/component that is read as a ViewChild ?您如何存根/模拟读取为ViewChild的指令/组件?

For example, using the simple directive from angular.io:例如,使用来自 angular.io 的简单指令:

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor() { }
}

Let's say that I am testing AppComponent and reads the HighlightDirective using ViewChild as:假设我正在测试AppComponent并使用ViewChild读取HighlightDirective为:

@ViewChild(HighlightDirective) theHighlightDirective: HighlightDirective

And the stubbed directive is:存根指令是:

@Directive({
  selector: '[appHighlight]'
})
export class StubbedHighlightDirective {
  constructor() { }
}

Since the component is trying to read HighlightDirective , even if you declare StubbedHighlightDirective in your unit tests, theHighlightDirective will be undefined .由于组件正在尝试读取HighlightDirective ,即使您在单元测试中声明StubbedHighlightDirectivetheHighlightDirective也将是undefined

Example:例子:

it('HighlightDirective is defined', () => {
    // This test fails
    expect(component.theHighlightDirective).toBeDefined();
});

You can get around this if you ignore some things in tslint or use the as keyword:如果您忽略 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();
});

Is there another way to cleanly stub out these kinds of ViewChild references?有没有另一种方法可以彻底清除这些 ViewChild 引用?

The problem is that you're using a class to find the child, and that class has been replaced by your stub.问题是您正在使用一个类来查找孩子,而该类已被您的存根取代。 You can use a matching exportAs link in your directive ( docs , blog post ) to make sure the real version and the stub have the same name.您可以在指令(文档博客文章)中使用匹配的exportAs链接来确保真实版本和存根具有相同的名称。

In the original directive decorator:在原始指令装饰器中:

@Directive({
    selector: '[appHighlight]',
    exportAs: 'appHighlight'
})
export class HighlightDirective {

In the stubbed directive:在存根指令中:

@Directive({
    selector: '[appHighlight]',
    exportAs: 'appHighlight'
})
export class StubbedHighlightDirective {

And then in the template where the directive is used:然后在使用指令的模板中:

<div appHighlight #appHighlight="appHighlight">

With all this done you'll need to update your @ViewChild definition to use the string instead of the class:完成所有这些后,您需要更新@ViewChild定义以使用字符串而不是类:

@ViewChild('appHighlight') theHighlightDirective: HighlightDirective

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM