我有一个Web应用程序,我有一个典型的问题,它需要不同环境的不同配置文件。某些配置作为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中声明实际调用普通上下文的变量吗?
答案 0 :(得分:37)
我可以推荐这样做,定义你的测试:
@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
答案 1 :(得分:5)
看着Biju的回答,我找到了一个有效的解决方案。
我创建了一个额外的上下文文件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(){
}
}
这可以在创建多个测试用例时节省一些工作。
答案 2 :(得分:2)
这里最好的方法是删除@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"/>
答案 3 :(得分:1)
@EnableConfigurationProperties需要存在(您也可以注释测试类),将加载来自test / resources的application-localtest.yml。 一个带有jUnit5的示例
@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties
@ContextConfiguration(classes = {YourClasses}, initializers = ConfigFileApplicationContextInitializer.class)
@ActiveProfiles(profiles = "localtest")
class TestActiveProfile {
@Test
void testActiveProfile(){
}
}
答案 4 :(得分:0)
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" };
}
}
这将设置配置文件,然后用于解析测试所需的依赖关系。