Тестирование компонент¶
Процесс тестирования Angular компонентов несколько отличается от тестирования сервисов и других сущностей, поскольку компонент — это результат взаимодействия класса и HTML-шаблона, что необходимо учитывать при тестировании.
Тест, проверяющий представление и класс, требует создания компонента в браузере, как в реально работающем приложении, что требует немного больших ресурсов.
Если вам необходимо убедиться в правильности описания логики класса, никак не влияющей на отображение, то отпадает необходимость определять компонент в структуре DOM.
Рассмотрим пример.
login-form.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
login-form.component.spec.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
Если у компонента нет зависимостей, то экземпляр его класса в тесте создается с помощью ключевого слова new
и без использования утилиты TestBed
.
Первый тест проверяет установку значений формы в момент инициализации компонента, второй — возникновение события validate
, инициируемое методом send()
.
Обратите внимание на то, как осуществляется проверка @Input()
и @Output()
свойств.
В процессе Angular component testing методы жизненного цикла не вызываются по умолчанию, как в реально работающем приложении. В тестах их вызов осуществляется явно.
Приступим к тестированию компонентов Angular с проверкой шаблона.
info-message.component.ts
1 2 3 4 5 6 7 8 9 10 11 |
|
info-message.component.spec.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Метод createComponent()
создает указанный компонент в DOM-дереве тестовой среды и возвращает объект типа ComponentFixture
, через который можно получить доступ к экземпляру компонента используя свойство componentInstance
и убедиться в том, что компонент инициализирован в DOM.
1 |
|
Другое полезное свойство объекта ComponentFixture
— nativeElement
. Значение свойства — объект типа HTMLElement
. У объектов HTMLElement
имеется метод querySelector
, который по заданному селектору осуществляет поиск элементов в пределах шаблона компонента и также возвращает объект или массив объектов типа HTMLElement
.
1 |
|
Свойства объекта nativeElement
напрямую зависят от среды выполнения теста. Например, вне браузера DOM-эмуляция просто невозможна, например, в приложении Angular Universal, именно поэтому имеется свойство debugElement
с объектом типа DebugElement
в качестве значения. В объекте также имеется объект nativeElement
, который работает универсально независимо от платформы. Поэтому рекомендуется при написании тестов придерживаться следующего формата:
1 2 |
|
Правда, если платформа не браузерная, то метод querySelector()
не сработает. Аналогом являются query()
и queryAll()
объекта debugElement
, принимающего результат, возвращаемый статическим методом css()
класса By
. Класс By
входит в состав библиотеки @angular/platform-browser
.
1 2 3 4 5 6 |
|
By.css()
принимает селектор в формате, аналогичному в querySelector()
.
В последних примерах проверялось статическое содержимое элементов HTML-разметки, т. е. текст присутствовал в шаблоне еще до компиляции компонента. Но при задании значения вот так
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
тесты выполнились бы, поскольку createComponent()
не связывает класс компонента с его шаблоном. Все переменные в таком случаем заменяются на пустые строки. Для инициации привязки необходимо вызвать detectChanges()
у объекта, возвращаемого после вызова метода createComponent()
.
1 2 3 4 5 6 7 |
|
Еще одна особенность приведенных ранее примеров — определение верстки в одном файле с определением класса. Но чаще всего (и это правильно) HTML-код и стили к нему выносятся в отдельные файлы. В таком случае необходимо вслед за методом configureTestingModule()
вызвать compileComponents()
.
Принудительная компиляция необходима только если тестирование Angular компонентов выполняется вне среды CLI. В случае запуска через Angular CLI компиляция происходит автоматически.
1 2 3 4 5 6 7 8 9 10 11 |
|
Асинхронный compileComponents()
возвращает Promise
и вызывается совместно с асинхронной функцией async()
из библиотеки @angular/core/testing
. Все синхронные операции после компиляции компонентов должны указываться в части then()
, иначе будет сгенерировано исключение.
Вызов метода абсолютно безвреден. Обращение к compileComponents()
без необходимости никак не повлияет на время и производительность тестирования.