Внедрение зависимостей должно сделать код менее зависимым от контейнера, чем это было бы при традиционной разработке на Java EE. POJO, составляющие ваше приложение, должны быть пригодны к тестированию в JUnit или TestNG вместе с объектами, экземпляры которых были созданы с помощью оператора new, без участия Spring или любого другого контейнера. Можно использовать объекты-имитации (mock objects) (в сочетании с другими полезными методами тестирования) для изолированного тестирования вашего кода. Если следовать рекомендациям по архитектуре Spring, то получаемое в результате чистое многоуровневое и компонентное представление кодовой базы облегчит модульное тестирование. Например, можно проводить тестирование объектов уровня служб с использованием функции-заглушки или объекта-имитации интерфейсов DAO или хранилища, без необходимости доступа к постоянно хранимым данным во время выполнения модульных тестов.

Истинные модульные тесты обычно производятся крайне быстро, поскольку нет необходимости в создании инфраструктуры среды выполнения. Упор на истинные модульные тесты как часть методологии разработки может повысить производительность. Возможно, вам и не пригодится этот раздел главы о тестировании, чтобы писать эффективные модульные тесты для ваших приложений на базе IoC. Однако для определенных сценариев модульного тестирования Spring Framework предоставляет объекты-имитации и вспомогательные классы тестирования, которые в этой главе рассматриваются.

Объект-имитация

Spring имеет ряд пакетов, предназначенных для использования объектов-имитаций:

  • Среда

  • JNDI

  • API-интерфейс сервлетов

  • Модуль Web Reactive в Spring

Окружение

Пакет org.springframework.mock.env содержит имитируемые реализации абстракций Environment и PropertySource (см. разделы "Профили определения бина" и "Абстракция PropertySource"). MockEnvironment и MockPropertySource полезны для разработки внеконтейнерных тестов для кода, который зависит от свойств, специфичных для среды.

JNDI

Пакет org.springframework.mock.jndi содержит частичную реализацию SPI-интерфейса JNDI, которую можно использовать для создания простой среды JNDI для тестовых комплектов или автономных приложений. Если, например, экземпляры DataSource из JDBC привязываются к тем же именам JNDI в тестовом коде, что и в контейнере Java EE, то можно повторно использовать как код приложения, так и конфигурацию в сценариях тестирования без изменений.

Поддержка объектов-имитаций JNDI в пакете org.springframework.mock.jndi официально устарела с версии Spring Framework 5.2, а предпочтение отдается готовым решениям от сторонних разработчиков, таким как Simple-JNDI.

API-интерфейс сервлетов

Пакет org.springframework.mock.web содержит полный набор объектов-имитаций API-интерфейса сервлетов (Servlet API), которые полезны для тестирования веб-контекстов, контроллеров и фильтров. Эти объекты-имитации предназначены для использования с фреймворком Spring Web MVC и в целом более удобны в пользовании, чем динамические объекты-имитации (например, EasyMock) или альтернативные объекты-имитации Servlet API (например, MockObjects).

Начиная со Spring Framework 5.0, объекты-имитации в org.springframework.mock.web базируются на Servlet API 4.0.

Инфраструктура Spring MVC Test основана на объектах-имитациях Servlet API, что обеспечивает среду интеграционного тестирования для Spring MVC. См. раздел "MockMvc".

Модуль Web Reactive в Spring

Пакет org.springframework.mock.http.server.reactive содержит имитируемые реализации ServerHttpRequest и ServerHttpResponse для использования в приложениях WebFlux. Пакет org.springframework.mock.web.server содержит объект-имитацию ServerWebExchange, который зависит от этих имитируемых объектов-запросов и объектов-ответов.

И MockServerHttpRequest, и MockServerHttpResponse происходят из тех же абстрактных базовых классов, что и специфичные для сервера реализации, и имеют с ними общую логику работы. Например, имитируемый объект-запрос становится незаменяемым после создания, но вы можете использовать метод mutate() из ServerHttpRequest для создания измененного экземпляра.

Для того чтобы имитируемый объект-ответ правильно реализовал контракт на запись и возвращал дескриптор завершения записи (то есть Mono<Void>), он по умолчанию использует Flux с cache().then(), который буферизирует данные и делает их доступными для утверждений в тестах. Приложения могут установить специальную функцию записи (например, для проверки бесконечного потока).

WebTestClient основывается на имитируемых объекте-запросе и объекте-ответе и обеспечивает поддержку тестирования приложений WebFlux без HTTP-сервера. Клиентскую часть также можно использовать для сквозного (end-to-end) тестирования с работающим сервером.

Вспомогательные классы для модульного тестирования

Spring содержит ряд классов, которые могут помочь в модульном тестировании. Они делятся на две категории:

  • Утилиты для тестирования общего назначения

  • Утилиты для тестирования в Spring MVC

Утилиты для тестирования общего назначения

Пакет org.springframework.test.util содержит несколько утилит общего назначения для использования в модульном и интеграционном тестировании.

ReflectionTestUtils – это коллекция служебных методов, основанных на рефлексии. Вы можете использовать эти методы в сценариях тестирования, если нужно изменить значение константы, установить не-public поле, вызвать не-public сеттер или вызвать не-public метод конфигурации или обратного вызова жизненного цикла при тестировании кода приложения в следующих случаях:

  • ORM-фреймворки (такие как JPA и Hibernate), которые допускают private или protected доступ к полям, в отличие от public сеттеров свойств в сущности предметной области.

  • Поддержка аннотаций Spring (таких как @Autowired, @Inject и @Resource), которые обеспечивают внедрение зависимостей для private или protected полей, сеттеров и конфигурационных методов.

  • Использование аннотаций, таких как @PostConstruct и @PreDestroy для методов обратного вызова жизненного цикла.

AopTestUtils – это коллекция связанных с АОП служебных методов. Вы можете использовать эти методы для получения ссылки на базовый целевой объект, скрытый за одним или несколькими прокси Spring. Например, если вы сконфигурировали бин в качестве динамического объекта-имитации с помощью такой библиотеки, как EasyMock или Mockito, и этот объект-имитация обернут в прокси Spring, вам может понадобиться прямой доступ к базовому объекту-имитации, чтобы сконфигурировать ожидаемые события для него и выполнить проверку. Для получения информации об основных АОП-утилитах в Spring см. разделы, посвященные AopUtils и AopProxyUtils.

Утилиты для тестирования в Spring MVC

Пакет org.springframework.test.web содержит ModelAndViewAssert, который вы можете использовать в сочетании с JUnit, TestNG или любым другим фреймворком тестирования для модульных тестов, работающих с объектами ModelAndView из Spring MVC.

Для модульного тестирования классов Controller из Spring MVC в качестве POJO используйте ModelAndViewAssert в сочетании с MockHttpServletRequest, MockHttpSession и т.д. из числа объектов-имитаций Servlet API. Для проведения тщательного интеграционного тестирования классов Controller из Spring MVC и REST в сочетании с конфигурацией WebApplicationContext для Spring MVC используйте фреймворк Spring MVC Test Framework.