Интеграционное тестирование в Spring: TestContext Framework, иерархии контекстов
При написании интеграционных тестов, основанных на загруженном Spring ApplicationContext, часто бывает достаточно тестирования в одном контексте. Однако бывают случаи, когда полезно или даже необходимо протестировать иерархию экземпляров ApplicationContext. Например, если вы разрабатываете веб-приложение Spring MVC, у вас обычно есть корневой WebApplicationContext, загруженный Spring ContextLoaderListener, и дочерний WebApplicationContext, загруженный Spring DispatcherServlet. Это приводит к иерархии родительско-дочернего контекста, в которой общие компоненты и конфигурация инфраструктуры объявляются в корневом контексте и используются в дочернем контексте веб-компонентами. Другой вариант использования можно найти в приложениях Spring Batch, где у вас часто есть родительский контекст, который обеспечивает конфигурацию для разделяемой пакетной инфраструктуры, и дочерний контекст для конфигурации определенного пакетного задания.
Вы можете писать интеграционные тесты, использующие контекстные иерархии, объявляя конфигурацию контекста с помощью аннотации @ContextHierarchy либо в отдельном тестовом классе, либо в иерархии тестовых классов. Если иерархия контекста объявлена для нескольких классов в иерархии тестовых классов, вы также можете объединить или переопределить конфигурацию контекста для определенного именованного уровня в иерархии контекста. При объединении конфигурации для заданного уровня в иерархии тип ресурса конфигурации (то есть файлы конфигурации XML или классы компонентов) должен быть согласованным. В противном случае вполне допустимо иметь разные уровни в иерархии контекста, настроенные с использованием разных типов ресурсов.
Примеры на основе JUnit Jupiter в этом разделе показывают общие сценарии конфигурации для интеграционных тестов, которые требуют использования контекстных иерархий.
Единый тестовый класс с контекстной иерархией
ControllerIntegrationTests представляет собой типичный сценарий тестирования интеграции для веб-приложения Spring MVC, объявляя иерархию контекста, состоящую из двух уровней: один для корневого WebApplicationContext (загружается с помощью TestAppConfig @Configuration класса) и один для сервлета диспетчера WebApplicationContext (загружается с помощью WebConfig @Configuration класса). Контекст WebApplicationContext, который автоматически подключается к экземпляру теста, является контекстом дочернего (то есть самым нижним контекстом в иерархии). В следующем листинге показан этот сценарий конфигурации:
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextHierarchy({
@ContextConfiguration(classes = TestAppConfig.class),
@ContextConfiguration(classes = WebConfig.class)
})
class ControllerIntegrationTests {
@Autowired
WebApplicationContext wac;
// ...
}
Иерархия классов с неявным родительским контекстом
Тестовые классы в этом примере определяют иерархию контекста в иерархии тестовых классов. AbstractWebTests объявляет конфигурацию корневого контекста WebApplicationContext в веб-приложении на основе Spring. Однако обратите внимание, что AbstractWebTests не объявляет @ContextHierarchy. Следовательно, подклассы AbstractWebTests могут при желании участвовать в иерархии контекста или следовать стандартной семантике для @ContextConfiguration. SoapWebServiceTests и RestWebServiceTests расширяют AbstractWebTests и определяют иерархию контекста с помощью @ContextHierarchy. В результате загружаются три контекста приложения (по одному для каждого объявления @ContextConfiguration), и контекст приложения, загружаемый на основе конфигурации в AbstractWebTests, устанавливается в качестве родительского контекста для каждого из контекстов, загруженных для конкретных подклассов. В следующем листинге показан этот сценарий конфигурации:
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
public abstract class AbstractWebTests {}
@ContextHierarchy(@ContextConfiguration("/spring/soap-ws-config.xml"))
public class SoapWebServiceTests extends AbstractWebTests {}
@ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml"))
public class RestWebServiceTests extends AbstractWebTests {}
Иерархия классов с объединенной конфигурацией иерархии контекстов
Классы в этом примере показывают использование именованных уровней иерархии для объединения конфигурации для определенных уровней в иерархии контекста. BaseTests определяет два уровня в иерархии: родительский и дочерний (parent и child). ExtendedTests расширяет BaseTests и инструктирует Spring TestContext Framework объединить конфигурацию контекста для дочернего уровня иерархии, гарантируя, что имена, объявленные в атрибуте name в @ContextConfiguration, являются дочерними. В результате загружаются три контекста приложения: один для /app-config.xml, один для /user-config.xml и один для {"/user-config.xml", "/order-config.xml"} . Как и в предыдущем примере, контекст приложения, загруженный из /app-config.xml, устанавливается как родительский контекст для контекстов, загруженных из /user-config.xml и {"/user-config.xml", "/order-config.xml "}. В следующем листинге показан этот сценарий конфигурации:
@ExtendWith(SpringExtension.class)
@ContextHierarchy({
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
@ContextConfiguration(name = "child", locations = "/user-config.xml")
})
class BaseTests {}
@ContextHierarchy(
@ContextConfiguration(name = "child", locations = "/order-config.xml")
)
class ExtendedTests extends BaseTests {}
Иерархия классов с переопределенной конфигурацией иерархии контекста
В отличие от предыдущего примера, этот пример демонстрирует, как переопределить конфигурацию для данного именованного уровня в иерархии контекста, установив для флага inheritLocations в @ContextConfiguration значение false. Следовательно, контекст приложения для ExtendedTests загружается только из /test-user-config.xml, а его родительский контекст установлен в контекст, загруженный из /app-config.xml. В следующем листинге показан этот сценарий конфигурации:
@ExtendWith(SpringExtension.class)
@ContextHierarchy({
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
@ContextConfiguration(name = "child", locations = "/user-config.xml")
})
class BaseTests {}
@ContextHierarchy(
@ContextConfiguration(
name = "child",
locations = "/test-user-config.xml",
inheritLocations = false
))
class ExtendedTests extends BaseTests {}
Загрязнение контекста внутри контекстной иерархии
Если вы используете @DirtiesContext в тесте, контекст которого настроен как часть иерархии контекста, вы можете использовать флаг hierarchyMode для управления очисткой кэша контекста.
Читайте также:
- Интеграционное тестирование в Spring: TestContext Framework, загрузка WebApplicationContext
- Интеграционное тестирование в Spring: TestContext Framework, кэширование контекста
- Интеграционное тестирование в Spring: TestContext Framework, конфигурация контекста с динамическими источниками свойств
Комментарии
Отправить комментарий