Кожен TestContext забезпечує керування контекстом та підтримку кешування для екземпляра тесту, за який він відповідає. Тестові екземпляри не отримують доступ до налаштованого ApplicationContext автоматично. Проте, якщо тестовий клас реалізує інтерфейс ApplicationContextAware, посилання на ApplicationContext передається тестовому екземпляру. Зверніть увагу, що AbstractJUnit4SpringContextTests та AbstractTestNGSpringContextTests реалізують ApplicationContextAware і, отже, забезпечують доступ до ApplicationContext автоматично.

ApplicationContext, позначений анотацією @Autowired

В якості альтернативи реалізації інтерфейсу ApplicationContextAware можна впровадити контекст програми для вашого тестового класу через анотацію @Autowired для поля або сеттера, як показано в наступному прикладі:

Java
@SpringJUnitConfig class MyTest { @Autowired  ApplicationContext applicationContext; // тіло класу... }
  1. Впроваджуємо ApplicationContext.
Kotlin
@SpringJUnitConfig class MyTest { @Autowired  lateinit var applicationContext: ApplicationContext // тіло класу... }
  1. Впроваджуємо ApplicationContext.

Аналогічно, якщо ваш тест налаштований на завантаження WebApplicationContext, то можна впровадити контекст веб-програми в тест таким чином:

Java
@SpringJUnitWebConfig  class MyWebAppTest { @Autowired  WebApplicationContext wac; // тіло класу... }
  1. Конфігуруємо WebApplicationContext.
  2. Впроваджуємо WebApplicationContext.
Kotlin
@SpringJUnitWebConfig  class MyWebAppTest { @Autowired  lateinit var wac: WebApplicationContext // тіло класу... }
  1. Конфігуруємо WebApplicationContext.
  2. Впроваджуємо WebApplicationContext.

Впровадження залежностей за допомогою анотації @Autowired забезпечується слухачем DependencyInjectionTestExecutionListener, який налаштований за умовчанням ( див. "Впровадження залежностей для тестових стендів").

Тестовим класам, які використовують фреймворк TestContext, не потрібно розширювати будь-який конкретний клас або реалізовувати певний інтерфейс для конфігурування свого контексту програми. Натомість конфігурація здійснюється шляхом оголошення анотації @ContextConfiguration на рівні класу. Якщо тестовий клас явно не оголошує розташування ресурсів контексту програми або компонентні класи, налаштований завантажувач ContextLoader визначає, як завантажити контекст із розташування за промовчанням або класів конфігурації за умовчанням. На додаток до розташування ресурсів контексту та компонентних класів, контекст програми також може бути налаштований за допомогою ініціалізаторів контексту програми.

У наступних розділах пояснюється, як використовувати анотацію @ContextConfiguration у Spring для налаштування тестового ApplicationContext за допомогою конфігураційних XML-файлів, скриптів Groovy, компонентних класів (зазвичай класів з анотацією @Configuration ) або ініціалізаторів контексту. Крім того, можна реалізувати та конфігурувати свій власний SmartContextLoader для розширених випадків використання.

Конфігурація контексту з використанням ресурсів XML

Щоб завантажити ApplicationContext для ваших тестів за допомогою конфігураційних XML-файлів, анотуйте ваш тестовий клас за допомогою @ContextConfiguration і сконфігуруйте атрибут locations за допомогою масиву, який містить дані про розташування ресурсів конфігураційних метаданих XML. Звичайний або відносний шлях (наприклад, context.xml) розглядається як ресурс classpath, який відноситься до пакета, в якому визначено тестовий клас. Шлях, що починається з косої межі, вважається абсолютним розташуванням classpath (наприклад, /org/example/config.xml). Шлях, що представляє URL ресурсу (тобто шлях з префіксами classpath:, file:, http: і т.д.), використовується як є.

Java
@ExtendWith(SpringExtension.class) // ApplicationContext буде завантажений з "/app-config.xml" і // "/test-config.xml" в корені шляху класів @ContextConfiguration(locations={"/app-config.xml", "/test-config.xml"})  class MyTest { // тіло класу... }
  1. Задаємо атрибут розташування у списку XML-файлів.
Kotlin
@ExtendWith(SpringExtension::class) // ApplicationContext буде завантажений з " /app-config.xml" і // "/test-config.xml" в корені шляху класів @ContextConfiguration("/app-config.xml", "/test-config.xml")  class MyTest { // тіло класу... }
  1. Задаємо атрибут розташування у списку XML-файлів.

Анотація @ContextConfiguration підтримує псевдонім для атрибуту locations через стандартний атрибут value з Java. Таким чином, якщо не потрібно оголошувати додаткові атрибути в анотації @ContextConfiguration, то можна опустити оголошення імені атрибута locations і оголосити розташування ресурсів, використовуючи скорочений формат, продемонстрований у наступному прикладі:

Java
@ExtendWith(SpringExtension.class) @ContextConfiguration({"/app-config.xml", "/test-config.xml"})  class MyTest { // тіло класу... }
  1. Задаємо XML-файли без використання атрибуту location.
Kotlin
 @ExtendWith(SpringExtension::class) @ContextConfiguration("/app-config.xml", "/test-config.xml")  class MyTest { // тіло класу... }
  1. Задаємо XML-файли без використання атрибуту location.

Якщо ви опустите атрибути location та value в анотації @ContextConfiguration, фреймворк TestContext спробує визначити розташування XML-ресурсу за умовчанням. Зокрема, GenericXmlContextLoader та GenericXmlWebContextLoader визначають місцезнаходження за умовчанням на основі імені тестового класу. Якщо ваш клас називається com.example.MyTest, GenericXmlContextLoader завантажує контекст програми з "classpath:com/example/MyTest-context.xml". У цьому прикладі показано, як це зробити:

Java
@ExtendWith(SpringExtension.class) // ApplicationContext буде завантажений з // "classpath:com/example/ MyTest-context.xml" @ContextConfiguration  class MyTest { // тіло класу... }
  1. Завантажуємо конфігурацію з розташування за промовчанням.
Kotlin
@ExtendWith(SpringExtension::class) // ApplicationContext буде завантажений з // "classpath:com/example/MyTest-context.xml" @ContextConfiguration  class MyTest { // тіло класу... }
  1. Завантажуємо конфігурацію з розташування за за замовчуванням.
Конфігурація контексту за допомогою сценаріїв Groovy

Щоб завантажити ApplicationContext для тестів за допомогою скриптів Groovy, які використовують Groovy Bean Definition DSL.
Також ви можете анотувати свій тестовий клас за допомогою @ContextConfiguration і налаштувати атрибут locations або value за допомогою масиву, що містить розташування ресурсів скриптів Groovy. Семантика пошуку ресурсів для скриптів Groovy така сама, як і для конфігураційних XML-файлів.

Активація підтримки скриптів Groovy
Підтримка використання скриптів Groovy для завантаження ApplicationContext у Spring TestContext Framework активується автоматично, якщо Groovy знаходиться в classpath.

У наступному прикладі показано, як задати конфігураційні файли Groovy:

Java
@ExtendWith(SpringExtension.class) // ApplicationContext буде завантажений з "/AppConfig.groovy" та // "/TestConfig.groovy" в корені шляху класів @ContextConfiguration({"/AppConfig.groovy", "/TestConfig.Groovy"})  class MyTest { // тіло класу... }
Kotlin
@ExtendWith(SpringExtension::class) // ApplicationContext буде завантажений з "/AppConfig.groovy" і // "/TestConfig.groovy" в корені шляху класів @ContextConfiguration("/AppConfig.groovy", "/TestConfig.Groovy" )  class MyTest { // тіло класу... }
  1. Визначення місцезнаходження файлів Groovy.

Якщо ви опустите атрибути locations і value з анотації @ContextConfiguration, фреймворк TestContext спробує визначити скрипт Groovy за умовчанням. Зокрема, GenericGroovyXmlContextLoader та GenericGroovyXmlWebContextLoader визначають місцезнаходження за умовчанням на основі імені тестового класу. Якщо ваш клас має ім'я com.example.MyTest, завантажувач контексту Groovy завантажить контекст вашої програми з "classpath:com/example/MyTestContext.groovy". У цьому прикладі показано, як використовувати значення за замовчуванням:

Java
@ExtendWith(SpringExtension.class) // ApplicationContext буде завантажений з // "classpath:com/ example/MyTestContext.groovy" @ContextConfiguration  class MyTest { // тіло класу... }
  1. Завантажуємо конфігурацію з розташування за промовчанням.
Kotlin
@ExtendWith(SpringExtension::class) // ApplicationContext буде завантажений з // "classpath:com/example/MyTestContext.groovy" @ContextConfiguration  class MyTest { // тіло класу... }
  1. Завантажуємо конфігурацію з розташування за промовчанням.
Одночасне оголошення XML-конфігурації та скриптів Groovy

Ви можете оголосити конфігураційні XML-файли та скрипти Groovy одночасно, використовуючи атрибут location або value в анотації @ContextConfiguration. Якщо шлях до розташування конфігурованого ресурсу закінчується .xml, він завантажується за допомогою XmlBeanDefinitionReader. В іншому випадку він завантажується за допомогою GroovyBeanDefinitionReader.

У наступному лістингу показано, як об'єднати обидва варіанти в інтеграційному тесті:

Java
@ExtendWith(SpringExtension.class) // ApplicationContext буде завантажений з // "/app-config.xml" і "/TestConfig.groovy" @ContextConfiguration({ "/app-config.xml", "/ TestConfig.groovy" }) class MyTest { // тіло класу... }
Kotlin
@ExtendWith (SpringExtension::class) // ApplicationContext буде завантажено з // "/app-config.xml" і "/TestConfig.groovy" @ContextConfiguration("/app-config.xml", "/TestConfig.groovy") class MyTest { // тіло класу... }
Конфігурація контексту з використанням компонентних класів

Щоб завантажити ApplicationContext для тестів за допомогою компонентних класів (див. розділ "Конфігурація контейнера на базі Java"), можна анотувати свій тестовий клас за допомогою @ContextConfiguration та налаштувати атрибут classes за допомогою масиву, що містить посилання на компонентні класи. У цьому прикладі показано, як це зробити:

Java
@ExtendWith(SpringExtension.class) // ApplicationContext буде завантажений з AppConfig і TestConfig @ContextConfiguration(classes = { AppConfig.class, TestConfig.class})  class MyTest { // тіло класу... }
  1. Завдання компонентних класів.
Kotlin
@ ExtendWith(SpringExtension::class) // ApplicationContext буде завантажений з AppConfig і TestConfig @ContextConfiguration(classes = [AppConfig::class, TestConfig::class])   class MyTest { // тіло класу... }
  1. Завдання компонентних класів.
Компонентні класи

Термін "компонентний клас" може стосуватися будь-якого з наступних:

  • Клас, анотований за допомогою @Configuration.

  • Компоненту (тобто класу, позначеному інструкціями @Component, @Service, @Repository або іншими стереотипними анотаціями).

  • Класу, що відповідає стандарту JSR-330, анотованого за допомогою анотацій javax.inject.

  • Будь-якому класу, що містить метод, анотовані @Bean.

  • Будь-якому іншому класу, який призначений для реєстрації як компонент Spring (тобто. бін Spring у ApplicationContext), що потенційно використовує переваги автоматичного виявлення та зв'язування єдиного конструктора без використання анотацій у Spring.

Дивіться javadoc по @Configuration та @Bean для отримання додаткової інформації про конфігурацію та семантику компонентних класів, звертаючи особливу увагу на розгляд анотування за допомогою @Bean у полегшеному режимі.

Якщо ви опустите атрибут classes в анотації @ContextConfiguration, фреймворк TestContext спробує визначити наявність конфігураційних класів за умовчанням. Зокрема, завантажувачі AnnotationConfigContextLoader та AnnotationConfigWebContextLoader виявляють усі статичні вкладені класи тестового класу, які відповідають вимогам до реалізації конфігураційного класу, як зазначено в javadoc @Configuration. Зверніть увагу, що ім'я класу конфігурації є довільним. Крім того, за бажанням тестовий клас може містити більше одного статичного вкладеного конфігураційного класу. >ApplicationContext для тестового класу:

Java
@SpringJUnitConfig  // ApplicationContext буде завантажений з // Статичний вкладений клас Config class OrderServiceTest { @Configuration static class Config { // цей бін буде впроваджений в клас OrderServiceTest @Bean OrderService orderService() { OrderService orderService = new OrderServiceImpl(); // задаємо властивості тощо. return orderService; } } @Autowired OrderService orderService; @Test void testOrderService() { // тестуємо orderService } }
  1. Завантаження інформації про конфігурацію з вкладеного класу Config.
Kotlin
@SpringJUnitConfig  // ApplicationContext буде завантажений з the nested Config class class OrderServiceTest { @Autowired lateinit var orderService: OrderService @Configuration class Config { // цей бін буде впроваджений в клас OrderServiceTest @Bean fun orderService(): OrderService { / / задаємо властивості і т.д. return OrderServiceImpl() } } @Test fun testOrderService() { // тестуємо orderService } }
  1. Завантаження інформації про конфігурацію з вкладеного класу Config.
Комбінування XML, скриптів Groovy та компонентних класів

Іноді бажано змішувати конфігураційні XML-файли , скрипти Groovy та компонентні класи (зазвичай це позначені анотацією @Configuration класи), щоб налаштувати ApplicationContext для ваших тестів. Наприклад, якщо ви використовуєте конфігурацію XML у виробничому середовищі, то можете вирішити, що варто вдатися до класів, помічених анотацією @Configuration, щоб налаштувати певні компоненти, керовані Spring, для ваших тестів, або навпаки.

Більше того, деякі сторонні фреймворки (наприклад, Spring Boot) надають відмінні засоби підтримки одночасного завантаження ApplicationContext з різних типів ресурсів (наприклад, конфігураційних XML-файлів, скриптів Groovy та класів з анотацією) @Configuration). Spring Framework історично не підтримував це для стандартних розгортань. Отже, більшість реалізацій SmartContextLoader, які Spring Framework поставляє в модулі spring-test, підтримують лише один тип ресурсів для кожного тестового контексту. Однак це не означає, що не можна використовувати обидва варіанти. Винятком із загального правила є те, що GenericGroovyXmlContextLoader та GenericGroovyXmlWebContextLoader підтримують одночасно конфігураційні XML-файли та скрипти Groovy. Більш того, сторонні фреймворки можуть підтримувати оголошення як locations, так і classes через анотацію @ContextConfiguration, а за стандартної підтримки тестування у фреймворку TestContext у вас є можливість, описані нижче.

Якщо необхідно використовувати розташування ресурсів (наприклад, XML або Groovy) та класи, анотовані @Configuration, щоб налаштувати ваші тести, то вам потрібно вибрати що- то з них як точка входу, і цей обраний клас або місце розташування повинні включати або імпортувати інші. Наприклад, у XML або скрипти Groovy можна включити класи, помічені анотацією @Configuration, використовуючи сканування компонентів або визначаючи їх як звичайні біни Spring, у той час як у класі, анотованому @Configuration, можна використовувати інструкцію @ImportResource, щоб імпортувати конфігураційні XML-файли або скрипти Groovy. Зверніть увагу, що така логіка роботи семантично еквівалентна тому, як ви конфігуруєте свою програму у виробничому середовищі: У виробничій конфігурації ви визначаєте або набір ресурсів XML або Groovy, або набір класів, помічених анотацією@Configuration, з яких завантажується ваш виробничий ApplicationContext, однак у вас все ще є можливість включати або імпортувати інший тип конфігурації.

Конфігурація контекстів за допомогою ініціалізаторів контексту

Щоб налаштувати ApplicationContext для ваших тестів за допомогою ініціалізаторів контексту, анотуйте ваш тестовий клас за допомогою @ContextConfiguration і конфігуруйте атрибут initializers за допомогою масиву, що містить посилання на класи, реалізують ApplicationContextInitializer. Оголошені ініціалізатори контексту використовуються для ініціалізації ConfigurableApplicationContext, який завантажується для ваших тестів. Зверніть увагу, що конкретний тип ConfigurableApplicationContext, що підтримується кожним оголошеним ініціалізатором, повинен бути сумісним з типом ApplicationContext, який створює SmartContextLoader (зазвичай це GenericApplicationContext). Більш того, порядок виклику ініціалізаторів залежить від того, чи реалізують вони інтерфейс Ordered зі Spring або чи позначені вони анотацією @Order або стандартною анотацією @Priority . У цьому прикладі показано, як використовувати ініціалізатори:

Java
@ExtendWith(SpringExtension.class) // ApplicationContext буде завантажений з TestConfig // та ініціалізований за допомогою TestAppCtxInitializer@ ContextConfiguration(classes = TestConfig.class, initializers = TestAppCtxInitializer.class)  class MyTest { // тіло класу... } 
  1. Завдання конфігурації за допомогою конфігураційного класу та ініціалізатора.
Kotlin
@ExtendWith(SpringExtension::class) // ApplicationContext буде завантажений з TestConfig // і ініціалізований за допомогою TestAppCtxInitializer @ContextConfiguration( classes = [TestConfig::class], initializers = [TestAppCtxIniti ])  class MyTest { // тіло класу... }
  1. Завдання конфігурації за допомогою конфігураційного класу та ініціалізатора.

Також можна повністю опустити оголошення конфігураційних XML-файлів, скриптів Groovy або компонентних класів в анотації @ContextConfiguration і натомість оголосити тільки класи ApplicationContextInitializer, які потім відповідатимуть за реєстрацію бінів у контексті – наприклад, шляхом програмного завантаження визначень бінів із XML-файлів чи конфігураційних класів . У цьому прикладі показано, як це зробити:

Java
@ExtendWith(SpringExtension.class) // ApplicationContext буде ініціалізований за допомогою EntireAppInitializer // який, як передбачається, реєструє біни в контексті @ContextConfiguration(initializers = EntireAppInitializer.class)  class MyTest { // тіло класу... }
  1. Завдання конфігурації за допомогою лише ініціалізатора.
Kotlin
@ExtendWith(SpringExtension::class) // ApplicationContext буде ініціалізований за допомогою EntireAppInitializer // який, як передбачається, реєструє біни в контексті @ContextConfiguration(initializers = [EntireAppInitializer::class])  class MyTest { // тіло класу... }
  1. Завдання конфігурації за допомогою лише ініціалізатора.
Спадкування конфігурації контексту

Анотація @ContextConfiguration підтримує булеви атрибути inheritLocations та inheritInitializers, які позначають, чи слід успадковувати розташування ресурсів або компонентні класи та ініціалізатори контексту, оголошені суперкласами. За умовчанням для обох прапорів є true. Це означає, що тестовий клас успадковує розташування ресурсів або компонентні класи, а також ініціалізатори контексту, оголошені будь-якими суперкласами. Зокрема, розташування ресурсів або компонентні класи для тестового класу додаються до списку розташування ресурсів або анотованих класів, оголошених суперкласами. Так само ініціалізатори для даного тестового класу додаються до набору ініціалізаторів, визначених суперкласами тестів. Таким чином, підкласи можуть розширювати розташування ресурсів, компонентні класи або ініціалізатори контексту.

Якщо атрибут inheritLocations або inheritInitializers в анотації @ContextConfiguratio.n встановлений у false, то розташування ресурсів або компонентні класи та ініціалізатори контексту для тестового класу, відповідно, "затіняють" і ефективно замінюють конфігурацію, визначену суперкласами.

Починаючи зі Spring Framework 5.3, конфігурація тестів може також успадковуватися від об'ємних класів. Див. подробиці у розділі "Конфігурація тестового класу з анотацією @Nested".

У наступному прикладі, в якому використовуються розташування XML-ресурсів, ApplicationContext для ExtendedTest завантажується з base-config.xml та extended-config.xml саме в такому порядку. Тому біни, визначені в extended-config.xml, можуть перевизначати (тобто замінювати) біни, визначені у base-config.xml. У наступному прикладі показано, як один клас може розширювати інший і використовувати як власний конфігураційний файл, так і конфігураційний файл суперкласу:

Java
@ExtendWith(SpringExtension.class ) // ApplicationContext буде завантажений з "/base-config.xml" // в корені classpath @ContextConfiguration("/base-config.xml")  class BaseTest { // тіло класу... } // ApplicationContext буде завантажений з "/base-config.xml" і // "/extended-config.xml" в корені classpath @ContextConfiguration("/extended-config .xml")  class ExtendedTest extends BaseTest { // тіло класу... }