2012-11-13 196 views
27

我有一个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中声明变量吗?

回答

23

我可以推荐做这种方式,定义你的测试是这样的:

@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

感谢。下面添加了一项改进。 –

+0

此方法不干净,您将不得不转到活动配置文件值应更改的属性文件。 – codebusta

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(){ 

    } 
} 

此创建时节省一些工作多个测试用例。

+0

因此,如果您想要加载其他属性,那么每次要运行测试时,都必须转至test-context.xml并更改属性文件路径?这与Spring Profiles的想法相矛盾。在这种情况下看看我的解决方案。 – codebusta

+0

@CodeBusta不,它是一个test-context.xml,仅用于加载常规上下文的测试。 –

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 setSystemProperty() { 
     System.clearProperty("spring.profiles.active"); 
    } 

    @Test 
    public void testContext(){ 

    } 
} 

而且你的测试context.xml中应具备以下条件:

<context:property-placeholder 
    location="classpath:META-INF/spring/config_${spring.profiles.active}.properties"/> 
+2

在@AfterClass中使用静态属性而不清理它们会导致严重的,难以分析的麻烦。 –

+0

你有其他建议吗?如果你有更好的解决方案,欢迎你把它放在这里。 – codebusta

+2

那么,正如我所说:至少通过AfterClass方法中的System.clearProperty()清理属性。或者使用一些规则,如https://stefanbirkner.github.io/system-rules/ –