I had recently a very interesting problem using Spring Boot and the automagic concerning the configuration.
The Problem
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demo.MyApplicationTests': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String demo.MyApplicationTests.url; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'my.url' in string value "${my.url}" at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE] Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'my.url' in string value "${my.url}" at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174) ~[spring-core-4.1.7.RELEASE.jar:4.1.7.RELEASE]
Configuration was not available in my Unit tests but it was working fine in the normal application. I spend a lot of time searching but without real good post concerning this issue.
This code already wasn’t working:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MyWebappApplication.class) @WebAppConfiguration public class MyApplicationTests { @Value("${my.url}") String url; @Test public void test() { System.out.println(url); } }
Even if my application.yml
/ application.properties
was looking good:
my: url: any kind of String we inject
The solution
Now here the working sample, do you see the difference?
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = MyWebappApplication.class) @WebAppConfiguration public class MyApplicationTests { @Value("${my.url}") String url; @Test public void test() { System.out.println(url); } }
Yes it is just the @SpringApplicationConfiguration
instead of the @ContextConfiguration
annotation. (Even if the first is itself just a meta-annotation of the second.) If you look into this new annotation you will find that it uses a different loader class, which makes the difference.
@ContextConfiguration(loader = SpringApplicationContextLoader.class) @Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface SpringApplicationConfiguration
That’s the trick. Having it in place the Spring Application configuration is successfully parsed an available in your unit test. Doesn’t matter if YAML
or just property
file.