Тестирование сервисов¶
Начнем с изучения тестирования сервисов Angular, поскольку именно сервисы проще всего покрываются тестами.
Ключевую роль в тестировании Angular приложений играет утилита TestBed из библиотеки @angular/core/testing. Она позволяет эмулировать модуль Testing Module, подобный модулю, создаваемого с декоратором @NgModule(). Тестовый модуль необходим для определения модулей, сервисов, компонентов и т. д., от которых зависим тест.
В TestBed имеется метод configureTestingModule(), которая принимает объект конфигурации аналогичный тому, что передается @NgModule().
1 2 3 4 5 | |
В коде выше определенный в providers тестового модуля сервис AppService становится доступным для использования каждому из выполняемых тестов. Получение экземпляра сервиса осуществляется методом get() утилиты TestBed.
get() может предоставить только те сервисы, которые указаны в свойстве providers модуля Testing Module.
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 | |
Разберем пример. Здесь описан один тест, который проверяет корректность работы метода getData() сервиса AppService. Метод getData() принимает число и возвращает его удвоенное значение.
Для сбора информации о вызовах метода getData() используется spyOn().
Обычно сервис не ограничивается только собственными методами. В сложном приложении сервисы взаимодействуют между собой, используя функционал друг друга.
В таких случаях общепринято использовать объекты Spy, чтобы не создавать ради одного или нескольких методов полноценный экземпляр еще одного сервиса.
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 | |
В примере createSpyObj() эмулирует сервис AppService с его единственным методом getData().
Если все тесты работают с одним набором данных, которые должен возвращать метод getData(), то в beforeEach() задать эти данные можно так:
1 2 3 | |
Инструменты также предусматривают возможность тестирования сервисов Angular, которые обращаются за данными к удаленному серверу. Ключевую роль здесь играют модуль HttpTestingModule и контроллер HttpTestingController.
Тестирование HTTP-сервисов не подразумевает обращение к удаленному API. Вместо этого все исходящие запросы перенаправляются в контроллер HttpTestingController.
app.service.ts
1 2 3 4 5 6 7 8 9 10 11 | |
app.service.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 35 36 37 38 39 40 41 | |
Как видно из примера, доступ к объекту запроса осуществляется с использованием метода expectOne() экземпляра класса HttpTestingController, идентифицирующего запрос в зависимости от переданного ему условия. Метод принимает параметром URL, на который осуществляется запрос, либо сам объект запроса. Например, можно отловить запрос с наличием определенного HTTP-заголовка или с определенным его значением.
Условию должен удовлетворять только один запрос. Если таких запросов будет несколько или они будут отсутствовать вовсе, будет сгенерировано исключение. Для работы с группой запросов необходимо использовать метод match(), который возвращает массив HTTP-запросов, попадающих под заданный критерий.
1 | |
В приведенном коде переменная req будет содержать массив всех запросов, сделанных на URL /api/data.
Возвращаемые в ответ на запрос данные передаются аргументом методу flush().
В конце каждого такого теста у экземпляра класса HttpTestingController нужно вызывать метод verify(), который подтверждает, что все запросы в рамках текущего теста были выполнены. Код идеально подходит для размещения в функции afterEach().
Для эмуляции ответа сервера с кодом ошибки, вторым аргументом методу flush() передается объект, где указывается статус и текст ошибки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
Для ошибки сетевого уровня можно использовать метода error() объекта запроса. Передаваемый параметр — объект типа ErrorEvent.
1 2 3 4 5 | |
В приведенных примерах fail() используется для принудительного завершения выполнения теста с ошибкой в тех местах, где Angular не сможет самостоятельно определить, правильно ли был выполнен сценарий.