Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

Therefore 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"/> 

Test:

@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 test case 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?

like image 485
Udo Held Avatar asked Nov 13 '12 15:11

Udo Held


People also ask

What are spring profiles used for?

Spring @Profile allow developers to register beans by condition. For example, register beans based on what operating system (Windows, *nix) your application is running, or load a database properties file based on the application running in development, test, staging or production environment.

What is the use of profiles in spring boot?

Spring Boot profiles Spring Boot allows to define profile specific property files in the form of application-{profile}. properties . It automatically loads the properties in an application. properties file for all profiles, and the ones in profile-specific property files only for the specified profile.


2 Answers

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 
like image 87
Biju Kunjummen Avatar answered Sep 26 '22 06:09

Biju Kunjummen


Looking at Biju's answer I found a working solution.

I created an extra context-file test-context.xml:

<context:property-placeholder location="classpath:config/spring-test.properties"/> 

Containing the profile:

spring.profiles.active=localtest 

And loading the test with:

@RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners({     TestPreperationExecutionListener.class     }) @Transactional @ActiveProfiles(profiles = "localtest") @ContextConfiguration(locations = {     "classpath:config/test-context.xml" }) public class TestContext {    @Test   public void testContext(){    } } 

This saves some work when creating multiple test-cases.

like image 20
Udo Held Avatar answered Sep 24 '22 06:09

Udo Held