Каковы преимущества использования @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. При таком подходе возникла проблема, когда не удавалось загрузить контекст приложения (например, из-за ошибки):

  1. После неудачной инициализации ContextClosedEvent не уволен - докеры не были остановлены и убраны.
  2. Когда контекст не загружается, инициализатор вызывается снова и снова для каждого запускаемого теста (не только для каждого класса теста - для каждого метода теста!).

Поэтому тесты продолжали убивать нашу CI-среду каждый раз, когда ошибка в контексте приложения приводила к сбою инициализации. Контейнеры для зависимых сервисов запускались для каждого метода тестирования, а затем не очищались.

Мы закончили тем, что использовали @ContextConfiguration и наличие двух отдельных контекстов для докеров и самого приложения. Таким образом, в случае вышеупомянутой ситуации докеры запускаются в отдельном контексте и, следовательно, живут там сами по себе и могут даже использоваться несколькими тестами Spring (из-за механизма кэширования контекста Spring).

Другие вопросы по тегам