Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@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>
like image 494
Markus Ratzer Avatar asked Jul 11 '13 18:07

Markus Ratzer


2 Answers

The issue here is you need a PropertySourcesPlaceholderConfigurer 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();
}
like image 199
Biju Kunjummen Avatar answered Oct 16 '22 17:10

Biju Kunjummen


With Spring 4, it's now possible to use TestPropertySource:

@TestPropertySource(value="classpath:/config/test.properties")

In order to load specific properties for a junit test

like image 40
Michael Avatar answered Oct 16 '22 17:10

Michael