24

I have a spring boot project and it works great. I now want to write tests for my application and I am running into some configuration headaches.

Spring boot created a test class for me called ApplicationTests. It's real simple and it looks like this:

@RunWith(SpringRunner.class)
@SpringBootTest
public class DuurzaamApplicationTests {
    @Test
    public void contextLoads() {
    }    
}

Now when I start the tests I get this error:

java.lang.IllegalArgumentException: Could not resolve placeholder 'company.upload' in value "${company.upload}"

I have a properties.yml file in the src/test/resources directory and for some reason it isn't loaded. I have tried all different kind of annotations from examples on the Internet and yet none of them work.

How can I tell spring boot tests to use an application.yml file to load the properties from?

Martijn Hiemstra
  • 927
  • 2
  • 14
  • 30
  • Possible duplicate of [Spring @PropertySource using YAML](https://stackoverflow.com/questions/21271468/spring-propertysource-using-yaml) – WesternGun Mar 06 '19 at 20:56

7 Answers7

19

We can use @TestPropertySource or @PropertySource to load the properties file.

Example:

@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource("classpath:properties.yml")
@ActiveProfiles("test")
public class DuurzaamApplicationTests {
    @Test
    public void contextLoads() {
    }    
}

Docs: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/TestPropertySource.html

Jakov
  • 879
  • 2
  • 17
  • 36
Barath
  • 5,093
  • 1
  • 17
  • 42
  • 6
    Doesn't work. I still get "Could not resolve placeholder 'company.upload' in value "${company.upload}". I have the application.yml located in the src/test/resources directory. – Martijn Hiemstra Aug 14 '17 at 07:03
  • can you share the project in gist or git ? – Barath Aug 14 '17 at 07:07
  • or define the value in application-test.yml under src/main/resources and by default springboot includes test profile while running test – Barath Aug 14 '17 at 07:08
  • 1
    The last tip helped solve the property value unfornately then the spring datasource doesn't get override. application-test.yml resolves the property value however the spring datasource is still being used instead of the supplied h2 database in application-test.yml. I have tried using both application files and also using @TestPropertySource and indiacting both application files and then the Value is unresolved again. Something very wierd with spring going on I guess. – Martijn Hiemstra Aug 14 '17 at 09:02
  • 6
    Use @ActiveProfiles("test") and try – Barath Aug 14 '17 at 09:04
  • That work's perfectly. The datasource is overriden and my properties are loaded. – Martijn Hiemstra Aug 14 '17 at 10:03
  • 1
    See my answer below. `.yml` is not supported, only `.properties` and `.xml` are. – WesternGun Jul 06 '18 at 11:55
14

To my surprise, when you load properties files in Spring Boot Test, .yml is not supported. It's noted in the documentation, although implicitly.

From the link above:

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/TestPropertySource.html

Supported File Formats

Both traditional and XML-based properties file formats are supported — for example, "classpath:/com/example/test.properties" or "file:/path/to/file.xml".

.yml is not mentioned.

And, after changing my .yml to .properties and rewrite the values in xx.xx.xx=value form, the key-values pairs can be read correctly.

So strange.

EDIT:

Now I find a ticket address this issue; seems a long-known bug in Spring.

https://github.com/spring-projects/spring-framework/issues/18486

WesternGun
  • 11,303
  • 6
  • 88
  • 157
  • If you don't want to rewrite your `.yml` you can also use the following for tests: `@SpringBootTest( properties = { "my.property=test" }` Note that the format for the properties has to be the one of `.properties` files, i.e. using `=` as separator. )` – geld0r Jul 24 '18 at 15:26
4

@PropertySource and @TestPropertySource do not work with YAML. See this.

I also tested it myself. Try creating 2 files - *.yml and *.properties and see it for yourself.

To make *.yml work most people use @SpringBootTest, but if it's not what you want and you would like to use @ContextConfiguration instead, you are in for a bit of surprise.

yuranos
  • 8,799
  • 9
  • 56
  • 65
0

For me the above solutions did not work and any environment variables were still overriding the test properties defined in @TestPropertySource even though https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html indicates that this source should have higher precedence than environment variables. The only solution that worked for me was to manually define a PropertyPlaceholderConfigurer bean in a test configuration class and set it with highest precedence.

This was with Spring Boot 1.5.15.RELEASE

@Configuration
@TestPropertySource(properties = "/application-test.properties")
@Slf4j
public class IntegrationTestConfiguration {

@Bean
public static PropertyPlaceholderConfigurer properties() {
    PropertyPlaceholderConfigurer ppc
          = new PropertyPlaceholderConfigurer();
    Resource[] resources = new ClassPathResource[]
          { new ClassPathResource( "/application-test.properties" ) };
    ppc.setLocations( resources );
    ppc.setIgnoreUnresolvablePlaceholders( true );
    ppc.setOrder( Ordered.HIGHEST_PRECEDENCE );

    return ppc;
}

/// ....

@RunWith( SpringRunner.class )
@ActiveProfiles( "test" )
@Import( IntegrationTestConfiguration.class )
@SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT )
public class MyTest {
GameSalutes
  • 1,762
  • 2
  • 18
  • 24
0

I had the same error message, my problem was a application.properties in src\test\resources which was missing the new properties

wutzebaer
  • 14,365
  • 19
  • 99
  • 170
0

Sometimes your application-test.properties file can't be found because it is in a subfolder off the class path.

for example this may not be found, because the file is actually not directly in the class path.

@TestPropertySource("classpath:application-test.properties")

but this will be found if the file is in the config folder off of a path in the class path

@TestPropertySource("classpath:config/application-test.properties")
Brad Parks
  • 66,836
  • 64
  • 257
  • 336
0

We can use annotation of @ActiveProfiles("test") that support application-test.yml or application-test.properties

qingliu
  • 66
  • 3