Угловое модульное тестирование - заглушка / насмешка над директивой со ссылкой в ​​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, даже если вы объявите 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 ответ

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