Это продолжение Тестирования угловых компонентов с мелкой визуализацией
Вы уже знаете, как использовать shallow-render
, верно? В этой статье мы рассмотрим некоторые из более сложных методов. Попутно я объясню, как эти методы могут помочь сделать ваш тестовый код более жестким и избавиться от еще большего количества шаблонов.
Рендеринг без HTML-шаблона
В первоначальном выпуске shallow-render
вы могли протестировать свои компоненты, набрав тот же HTML-код, что и в вашем шаблоне. Это может быть хорошим примером того, как использовать компонент в ваших спецификациях:
Вы можете видеть, что когда вам понадобятся более продвинутые привязки, мы имитируем модель шаблона / контроллера в нашем тесте, указав шаблон HTML для визуализации вместе с переменными области видимости в объекте bind
, переданном в средство визуализации.
Это работает хорошо, но мы могли бы немного упростить это, удалив шаблон и просто указав привязки.
Это мой шаблон. Это позволяет вам полностью игнорировать язык шаблонов Angular, но мы сохраняем безопасность типов, потому что аргумент bind
должен соответствовать типам с входными данными компонента.
Вы могли заметить, что во втором тесте мы не отправляем обработчик кликов. Когда shallow-render
обрабатывает ваш компонент, он проверяет метаданные и автоматически отслеживает источники событий для вас. Это означает, что для определения того, генерируются ли события должным образом, вы можете просто подтвердить, что эмиттер был вызван с правильными выходами. Это немного удобнее, чем тестирование с помощью шаблонов, и позволяет избежать нескольких сценариев, которые могут облегчить чтение тестов:
Плюсы:
- Меньше кода! (не нужно указывать привязки событий)
- Требует, чтобы свойства привязки соответствовали именам со свойствами компонента, что может помочь избежать путаницы имени привязки со свойством компонента.
Минусы:
- Иногда желательно иметь HTML-код в вашей спецификации в качестве примера, чтобы другие разработчики могли сразу увидеть его использование.
- Не поддерживает отображение проецируемого содержимого или директив.
Директивы по тестированию
Директивы в Angular очень похожи на компоненты; настолько, что они часто упоминаются как одно и то же в кодовой базе Angular. Shallow довольно легко поддерживает директивы тестирования.
Обратите внимание: поскольку директивы должны быть прикреплены к существующему элементу HTML, вы должны указать шаблон HTML для средства визуализации. Также обратите внимание, что element
, возвращаемый при рендеринге, - это div
, к которому директива была прикреплена в HTML.
Использование сменных модулей
Распространенным шаблоном в сообществе Angular является предоставление тестового модуля, который представляет собой замену модулю, разработанному специально для тестов. Angular делает это довольно часто, вот HttpClientTestingModule
, который используется для замены фиктивного запросчика для экземпляров HttpClient
.
Мы можем использовать их в наших тестах, «заменив» исходный модуль тестовым модулем.
shallow.replaceModule(HttpClientModule, HttpClientTestingModule)
Вот пример теста с использованием модуля тестирования:
Здесь много чего происходит. Большая часть сложности здесь связана с тем, что тестирование HttpClient
запросов в Angular немного многословно. Вот несколько примечаний (в том порядке, в котором вы их прочтете из теста).
- В наших тестах мы используем
fakeAsync
иasync
.fakeAsync
позволяет нам вручную управлять потоком цепочек обещаний в нашем компоненте. - Мы используем метод shallow
get
для извлечения инъекций из модуля. (мы также должны использоватьHttpTestingController
, потому что Angular использовал абстрактный класс). - Мы устанавливаем наши
HttpClient
mocks, а затемtick
. Это разрешает цепочку обещаний запроса в конструкторе компонента, который, в свою очередь, обновляет свойствоlabelText
компонента. - Поскольку мы инициировали изменение пользовательского интерфейса, мы должны
detectChanges
, прежде чем делать утверждения для компонента.
Примечание: это надуманный пример, предназначенный только для предоставления некоторых примеров тестирования с мелкой визуализацией. В реальном приложении я всегда рекомендовал бы заключать вызовы к конечным точкам HTTP в класс обслуживания, который инкапсулирует связь HTTP. Это сделает ваше приложение и тестирование намного проще!
Тестирование с помощью RouterModule
Тестирование приложений, использующих модуль Angular Routing, является горячей темой в списке проблем с мелкой отрисовкой. С некоторыми из недавних дополнений в shallow-render
теперь все довольно просто. Здесь мы снова обнаруживаем, что Angular предоставил нам тестовый модуль для маршрутизации (RouterTestingModule
). Нам просто нужно заменить исходный RouterModule
тестовой версией и убедиться, что наш тестовый модуль настроен в соответствии с документацией Angular.
Это простейшая форма тестирования маршрутов. Вы даже можете поставить RouterTestingModule
замену глобально, используя alwaysReplaceModule
, так что вам не нужно помнить о замене в каждой спецификации.
Использование селекторов ViewChild / ContentChild
Angular позволяет создавать компоненты, которые хорошо сочетаются друг с другом. Иногда внешний компонент может ссылаться на дочерний компонент с помощью ContentChild
селекторов. Вот пример компонента списка, который автоматически активирует первый элемент в списке.
Поскольку shallow автоматически имитирует компонент list-item
в наших тестах, нам нужно имитировать функцию ListItemComponent
activate
, чтобы мы могли убедиться, что она вызывается для первого элемента в списке. Здесь нам пришлось использовать стиль рендеринга HTML Template, чтобы мы могли рендерить дочерние компоненты в наш ListContainer
компонент.
Дополнительное примечание об изоляции в модульных тестах
Обратите внимание: поскольку это тест для ListItemContainer
, нам все равно, что метод ListItem#activate
делает сListItem
, потому что тесты для этого ListItem
поведения должны входить в тесты для ListItem
. Следуя этой модели изоляции тестируемого компонента, мы гарантируем, что мы сможем реорганизовать поведение активации ListItem
без ненужного нарушения тестов для ListItemContainer
. Нет ничего более неприятного, чем рефакторинг внутреннего устройства одного компонента с обратной совместимостью и нарушение модульных тестов для некоторых других компонентов, которые на самом деле не сломались!