Markus R Markus R -4 years ago 119
Java Question

@Value not set via Java-configured test context

I've got a Maven project which uses Java-configured Spring (

@Configuration
etc.). Properties which are referenced by
@Value
are stored in different places, e.g. Tomcat's context.xml.

For testing I've created a .properties file to provide some values for the components and services. In my JUnit test (which uses a spring test context) this .properties file is added via
@PropertySource
. The problem is that the values will not be loaded from the file, instead the value identifier is set as value, e.g.
${someFlag:false}
(so I get ClassCastExceptions for any other than String). Also the default value will not be set, so I think, the values won't be processed at all.

I'm sure Spring finds this file because when I change the value of
@PropertySource
I get some FileNotFoundException. Nevertheless I've tried different variants to point to this file an all have worked (tested by renaming which produced FileNotFoundException):


  • classpath:/test.properties (my preferred notation)

  • /test.properties

  • file:src/test/resources/test.properties



I'm also sure that Spring itself works, because when I remove the
@Value
, the class under test is injected via
@Autowired
in my test as expected.

Down below you'll find the problem scenario stripped down as much as possible. For versions and dependencies please see the pom.xml at the bottom.

MyService.java



package my.package.service;

// Imports

@Service
public class MyService {

@Value("${someFlag:false}")
private Boolean someFlag;

public boolean hasFlag() {
return BooleanUtils.isTrue(someFlag);
}
}


MyConfiguration.java



@Configuration
@ComponentScan(basePackages = {"my.package.service"})
public class MyConfiguration {
}


MyServiceComponentTest.java



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyTestConfiguration.class})
public class MyServiceComponentTest {

@Autowired
private MyService service;

@Test
public void hasFlagReturnsTrue() {
assertThat(service.hasFlag(), is(true));
}
}


MyTestConfiguration.java



@Configuration
@Import({MyConfiguration.class})
@PropertySource("classpath:/test.properties")
public class MyTestConfiguration {
}


src/test/resources/test.properties



someFlag=true


pom.xml



<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>3.2.3.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

Answer Source

The issue here is you need a PropertyPlaceholderConfigurer also which is actually responsible for resolving the ${..} fields, just add another bean which creates this bean:

@Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
    return new PropertySourcesPlaceholderConfigurer();
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download