Thomas Beauvais
Thomas Beauvais

Reputation: 1656

@TestPropertySource doesn't work for JUnit test with AnnotationConfigContextLoader in Spring 1.2.6

It doesn't seem that anything I do in Spring 4.1.17 with Spring Boot 1.2.6.RELEASE works at all. I just want to access the application properties and override them with test if necessary (without using the hack to inject a PropertySource manually)

this doesn't work..

@TestPropertySource(properties = {"elastic.index=test_index"})

nor does this..

@TestPropertySource(locations = "/classpath:document.properties")

nor this..

@PropertySource("classpath:/document.properties")

full test case..

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@TestPropertySource(properties = {"elastic.index=test_index"})
public class PropertyTests {
    @Value("${elastic.index}")
    String index;

    @Configuration
    @TestPropertySource(properties = {"elastic.index=test_index"})
    static class ContextConfiguration {
    }

    @Test
    public void wtf() {
        assertEquals("test_index", index);
    }
}

resulting in

org.junit.ComparisonFailure: 
Expected :test_index
Actual   :${elastic.index}

It seems there is a lot of conflicting information between 3.x and 4.x and I can't find anything that will work for sure.

Any insight would be gratefully appreciated. Cheers!

Upvotes: 45

Views: 163818

Answers (8)

To achieve the functionality of using primary src/main/resources/application.yml config file for tests and override only specific fields via src/test/resources/application-test.yml

It was needed to add these annotations to the main test class:

@SpringBootTest
@TestPropertySource(locations = "classpath:application-test.yml")
@ActiveProfiles("test")

Spring boot version: 3.3.2

Upvotes: 0

goldlil
goldlil

Reputation: 121

If you have this problem and you're trying with yaml as properties file keep in mind that spring @TestPropertySource and @PropertySource doesn't work with yaml file, and properties won't be loaded properly.

https://github.com/spring-projects/spring-boot/issues/10772#issuecomment-339581902

Upvotes: 12

S.Sriniavasulu
S.Sriniavasulu

Reputation: 49

I had issue with @TestPropertySource. test.properties not found

below is the one before fixed

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ExtContext.class)
@TestPropertySource(locations = "classpath: test.properties")

i removed space between classpath: and test.properties as below

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ExtContext.class)
@TestPropertySource(locations = "classpath:test.properties")

This worked for me, When test.properties is not found in classpth. misht work for you aswell

Upvotes: 0

sorrymissjackson
sorrymissjackson

Reputation: 2705

I used the locations property of @TestPropertySource to override (or add) properties.

This worked for me (spring 4.2.4):

@TestPropertySource(locations = {
   "classpath:test.properties",
   "classpath:test-override.properties" })

But overriding properties like below didn't:

@TestPropertySource(
  locations = {"classpath:test.properties"},
  properties = { "key=value" })

Even though the javadoc says that those properties have highest precedence. A bug maybe?

Update

The bug should be fixed in Spring boot version 1.4.0 and up. See the commit which closes the issue. By now, properties declared in the presented way should get precedence.

Upvotes: 19

Swarit Agarwal
Swarit Agarwal

Reputation: 2648

For Me @TestPropertySource("classpath:xxxxxxxx.properties") worked

Upvotes: 4

Thomas Beauvais
Thomas Beauvais

Reputation: 1656

Turns out the best way (until Spring fixes this oversight) is to a PropertySourcesPlaceholderConfigurer that will bring in test.properties (or whatever you want) and @Import or extend that @Configuration.

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.IOException;

@Configuration
public class PropertyTestConfiguration {
    @Bean
    public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() throws IOException {
        final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
        ppc.setLocations(ArrayUtils.addAll(
                        new PathMatchingResourcePatternResolver().getResources("classpath*:application.properties"),
                        new PathMatchingResourcePatternResolver().getResources("classpath*:test.properties")
                )
        );

        return ppc;
    }

}

This allows you to define defaults in application.properties and override them in test.properties. Of course, if you have multiple schemes, then you can configure the PropertyTestConfiguration class as necessary.

And use this in a unit test.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class PropertyTests {
    @Value("${elastic.index}")
    String index;

    @Configuration
    @Import({PropertyTestConfiguration.class})
    static class ContextConfiguration {
    }
}

Upvotes: 18

Don Bottstein
Don Bottstein

Reputation: 1660

Your use of @Value requires a PropertySourcesPlaceholderConfigurer bean to resolve ${...} placeholders. See the accepted answer here: @Value not set via Java-configured test context

Upvotes: 13

ninja.coder
ninja.coder

Reputation: 9648

Have you tried using @PropertySource("classpath:document.properties") or @PropertySource("classpath*:document.properties") ?

Upvotes: 3

Related Questions