Угловое модульное тестирование - заглушка / насмешка над директивой со ссылкой в ​​ViewChild - PullRequest
0 голосов
/ 31 января 2019

Как вам заглушить / смоделировать директиву / компонент, который читается как 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?

1 Ответ

0 голосов
/ 22 февраля 2019

Проблема в том, что вы используете класс, чтобы найти ребенка, и этот класс был заменен вашей заглушкой.Вы можете использовать соответствующую ссылку 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
...