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.