Весенние профили и тестирование
У меня есть веб-приложение, где у меня есть типичная проблема, которая требует разных файлов конфигурации для разных сред. Некоторая конфигурация размещается на сервере приложений как источники данных JNDI, однако некоторая конфигурация остается в файлах свойств.
Поэтому я хочу использовать функцию профилей Spring.
Моя проблема в том, что я не запускаю тестовый пример.
context.xml:
<context:property-placeholder
location="classpath:META-INF/spring/config_${spring.profiles.active}.properties"/>
Тестовое задание:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration(locations = {
"classpath:context.xml" })
public class TestContext {
@Test
public void testContext(){
}
}
Кажется, проблема в том, что переменная для загрузки профиля не решена:
Caused by: java.io.FileNotFoundException: class path resource [META-INF/spring/config_${spring.profiles.active}.properties] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:157)
at org.springframework.core.io.support.PropertiesLoaderSupport.loadProperties(PropertiesLoaderSupport.java:181)
at org.springframework.core.io.support.PropertiesLoaderSupport.mergeProperties(PropertiesLoaderSupport.java:161)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:138)
... 31 more
Текущий профиль должен быть установлен с аннотацией @ActiveProfile
. В качестве теста я не смогу использовать web.xml
. Если возможно, я бы также хотел избежать опций времени выполнения. Тест должен выполняться как есть (если это возможно).
Как правильно активировать профиль? Можно ли установить профиль с помощью context.xml? Могу ли я объявить переменную в test-context.xml, которая фактически вызывает нормальный контекст?
Ответы
Ответ 1
Могу ли я рекомендовать это сделать так, определите свой тест следующим образом:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration
public class TestContext {
@Test
public void testContext(){
}
@Configuration
@PropertySource("classpath:/myprops.properties")
@ImportResource({"classpath:context.xml" })
public static class MyContextConfiguration{
}
}
со следующим содержимым в файле myprops.properties:
spring.profiles.active=localtest
При этом ваш второй файл свойств должен быть разрешен:
META-INF/spring/config_${spring.profiles.active}.properties
Ответ 2
Глядя на ответ Биджу, я нашел рабочее решение.
Я создал дополнительный файл-контекст test-context.xml
:
<context:property-placeholder location="classpath:config/spring-test.properties"/>
Содержит профиль:
spring.profiles.active=localtest
И загрузите тест с помощью
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration(locations = {
"classpath:config/test-context.xml" })
public class TestContext {
@Test
public void testContext(){
}
}
Это экономит некоторую работу при создании нескольких тестовых случаев.
Ответ 3
Наилучшим подходом здесь является удаление аннотации @ActiveProfiles и выполнение следующих действий:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ContextConfiguration(locations = {
"classpath:config/test-context.xml" })
public class TestContext {
@BeforeClass
public static void setSystemProperty() {
Properties properties = System.getProperties();
properties.setProperty("spring.profiles.active", "localtest");
}
@AfterClass
public static void unsetSystemProperty() {
System.clearProperty("spring.profiles.active");
}
@Test
public void testContext(){
}
}
И ваш test-context.xml должен иметь следующее:
<context:property-placeholder
location="classpath:META-INF/spring/config_${spring.profiles.active}.properties"/>
Ответ 4
public class LoginTest extends BaseTest {
@Test
public void exampleTest( ){
// Test
}
}
Унаследован от базового тестового класса (этот пример - testng
а не jUnit
, но ActiveProfiles
- то же самое):
@ContextConfiguration(locations = { "classpath:spring-test-config.xml" })
@ActiveProfiles(resolver = MyActiveProfileResolver.class)
public class BaseTest extends AbstractTestNGSpringContextTests { }
MyActiveProfileResolver
может содержать любую логику, необходимую для определения, какой профиль использовать:
public class MyActiveProfileResolver implements ActiveProfilesResolver {
@Override
public String[] resolve(Class<?> aClass) {
// This can contain any custom logic to determine which profiles to use
return new String[] { "exampleProfile" };
}
}
Это устанавливает профиль, который затем используется для разрешения зависимостей, требуемых тестом.