I have a spring boot application. I am writing Junit tests. I am trying to inject values from application.properties (defined in src/main/resources/application.properties) and a Status bean configured in AppConfig (src/main/java/hello/AppConfig.java). I see that the bean is autowired (through debugger it is not null) but the values are not set.
Here is application.properties
src/main/resources/application.properties
app.name=rest-service
app.version=1.0.0-SNAPSHOT
src/main/java/hello/AppConfig.java
@Configuration
public class AppConfig {
@Value("${app.version}")
private String version;
@Value("${app.name}")
private String name;
@Bean
public Status status(){
return new Status(name,version);
}
}
//Status is a simple pojo with name and version fields
src/test/java/hello/GreetingControllerTests.java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ContextConfiguration(classes={hello.TestConfig.class,hello.AppConfig.class})
@WebAppConfiguration
public class GreetingControllerTests {
@Autowired
Environment envi;
@Autowired
Status status;
@Value("${app.name:notConfigured}")
String appName;
private String env;
@Before
public void init(){
System.out.println(status.getName());
System.out.println(appName);
env=envi.getActiveProfiles()[0];
}
@Test
public void should_fail(){
if (env.equalsIgnoreCase("DEV")){
assertThat(false).isFalse();
}
if (env.equalsIgnoreCase("QA1")){
System.out.println("failing the test");
fail();
}
}
}
I set debugger in the init method and found that both appName
and status
bean with right values set are NOT injected. Status bean is injected though. just the values are not set.
Thank you for sharing the project. It made it a lot easier to work with. Please see my pull request (with comments) to understand how I got it all working.
* Update * You had annotations being overwritten due to mixing some old Spring annotations with newer annotations. Credits to spring-boot properties not @Autowired for pointing me to the solution based on a google search for application.properties not being populated in the environment
.
If you look at the @SpringApplicationConfiguration
:
@ContextConfiguration(loader = SpringApplicationContextLoader.class)
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Deprecated
public @interface SpringApplicationConfiguration {
It is actually composed of a number of other annotations. The important one is the @ContextConfiguration
. For the @SpringApplicationConfiguration
it uses a loader and that loader is scanning the classpath for appropriate configuration files along with components to load (one being the thing that reads the application.properties into the environment). Within the test you override that annotation with your declaration:
@ContextConfiguration(classes={hello.TestConfig.class,hello.AppConfig.class})
This forces Spring to only load the TestConfig and AppConfig classes without scanning for any other configuration files. Commenting out that annotation and running it will make the test pass and debugging the init() method will show the values injected.