Каковы преимущества использования @ContextHierarchy перед чистой @ContextConfiguration
Привет, я не понимаю, какие преимущества дает мне использование @ContextHierarchy, как показано ниже:
@ContextHierarchy({
@ContextConfiguration("/test-db-setup-context.xml"),
@ContextConfiguration("FirstTest-context.xml")
})
@RunWith(SpringJUnit4ClassRunner.class)
public class FirstTest {
...
}
@ContextHierarchy({
@ContextConfiguration("/test-db-setup-context.xml"),
@ContextConfiguration("SecondTest-context.xml")
})
@RunWith(SpringJUnit4ClassRunner.class)
public class SecondTest {
...
}
за использование одного @ContextConfiguration с аргументом location, как показано ниже:
@ContextConfiguration(locations = {"classpath:test-db-setup-context.xml", "FirstTest-context.xml", "SecondTest-context.xml" })
В каждом случае контексты приложения являются общими для разных тестовых классов junit.
1 ответ
Разница в том, что компоненты в каждом контексте внутри иерархии контекста не могут видеть компоненты в другом контексте. Таким образом, вы можете выделить различные части тестируемого элемента.
Важно отметить, что в случае @ContextHierarchy
мы получаем отдельные контексты, которые имеют отдельные жизненные циклы (инициализация, завершение работы). Это важно, потому что, например, они могут потерпеть неудачу независимо.
Практический пример из моего двора. У нас есть приложение Spring, которое связывается с некоторыми внешними сервисами. Мы хотели тест E2E, который запускает эти зависимые сервисы и запускает тесты. Таким образом, мы добавили инициализатор к нашему @ContextConfiguration
:
@ContextConfiguration{classes = TheApp.class, initializers = DockerInitializer.class}
public class TheAppE2ETests {
// ...
}
Инициализатор готовил внешние службы (запускает Dockers), настраивая свойства, чтобы приложение могло запускаться, и присоединяясь к событию закрытия контекста, чтобы можно было очистить Dockers. При таком подходе возникла проблема, когда не удавалось загрузить контекст приложения (например, из-за ошибки):
- После неудачной инициализации
ContextClosedEvent
не уволен - докеры не были остановлены и убраны. - Когда контекст не загружается, инициализатор вызывается снова и снова для каждого запускаемого теста (не только для каждого класса теста - для каждого метода теста!).
Поэтому тесты продолжали убивать нашу CI-среду каждый раз, когда ошибка в контексте приложения приводила к сбою инициализации. Контейнеры для зависимых сервисов запускались для каждого метода тестирования, а затем не очищались.
Мы закончили тем, что использовали @ContextConfiguration
и наличие двух отдельных контекстов для докеров и самого приложения. Таким образом, в случае вышеупомянутой ситуации докеры запускаются в отдельном контексте и, следовательно, живут там сами по себе и могут даже использоваться несколькими тестами Spring (из-за механизма кэширования контекста Spring).