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


person yoonjesung    schedule 31.01.2019    source источник
comment
Извините, но я не думаю, что это возможно   -  person Amir Arbabian    schedule 31.01.2019


Ответы (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
person Robin K    schedule 22.02.2019