Udo Held Udo Held - 10 days ago 7
Java Question

Spring profiles and Testing

I've got a web application where I have the typical problem that it requires different configuration files for different environments. Some configuration is placed in the application server as JNDI datasources, however some configuration stays in property files.

Therefor I want to use the Spring profiles feature.

My problem is that I don't get the test case running.

context.xml:

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


TestCase:

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration(locations = {
"classpath:context.xml" })
public class TestContext {

@Test
public void testContext(){

}
}


The problem seems to be that the variable for loading the profile isn't resolved:

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


The current profile should be set with the
@ActiveProfile
annotation. As it's a testcase I won't be able to use the
web.xml
. If possible I'd like to avoid runtime options as well. The test should run as is (if possible).

How can I properly activate the profile?
Is it possible to set the profile with a context.xml?
Could I declare the variable in a test-context.xml that is actually calling the normal context?

Answer

Can I recommend doing it this way, define your test like this:

@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{

  }
}

with the following content in myprops.properties file:

spring.profiles.active=localtest

With this your second properties file should get resolved:

META-INF/spring/config_${spring.profiles.active}.properties