I'm getting this exception on my test excution:
UnsatisfiedDependencyException: Error creating bean with name 'net.gencat.transversal.espaidoc.mongo.GridFSTest': Unsatisfied dependency expressed through field 'resourceProperties'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'net.gencat.transversal.espaidoc.ResourcesConfigProperties' available: expected at least 1 bean which qualifies as autowire candidate.
So, I think message is so clear enough: ResourcesConfigProperties is not satisfied.
My test:
RunWith(SpringRunner.class)
@SpringBootTest()
public class GridFSTest {
 @Autowired
 private GridFsTemplate gridFsTemplate;
 @Autowired
 private ResourcesConfigProperties resourceProperties;
 public URL getHugeResource() {
 try {
 return Paths
 .get(this.resourceProperties.getHuge())
 .toUri()
 .toURL();
 } catch (MalformedURLException e) {
 return null;
 }
 }
 @Test
 public void storeHugeFile() throws IOException {
 URL resource = this.getHugeResource();
 this.gridFsTemplate.store(
 resource.openStream(),
 resource.getPath(),
 "mime"
 );
 }
}
and ResourcesConfigProperties is:
@ConfigurationProperties(prefix = "files")
public class ResourcesConfigProperties {
 private String huge;
 /**
 * @return the huge
 */
 public String getHuge() {
 return huge;
 }
 /**
 * @param huge the huge to set
 */
 public void setHuge(String huge) {
 this.huge = huge;
 }
}
into my src/test/resources I have my application.properties file:
files.huge: /home/jcabre/Downloads/1GB.zip
Any ideas?
EDIT
Main Spring boot application:
@SpringBootApplication(
 //scanBasePackages = { "cat.gencat.ctti.canigo.arch.web.rs" },
 exclude = JmxAutoConfiguration.class
)
@EnableConfigurationProperties({
 ApiProperties.class,
 FileStoreProperties.class
})
@Import(RedisConfiguration.class)
public class ApiApplication {
 public static void main(String[] args) {
 SpringApplication.run(ApiApplication.class, args);
 }
}
 3 Answers 3
TL;DR:
It is happening, because the @ConfigurationProperties are not managed by the application context you build in tests, although they will be load when the application launches, because you have @EnableConfigurationProperties on your app main class.
@EnableConfigurationProperties on main class only affect the application context you have when you bootRun, but not that in a @SpringBootTest. The application context you build in tests could be, under many circumstances, distinct with that of bootRun, just like in your case.
You can add @Component to make the context be aware of it, both in gradle bootRun and in gradle test. It's the easiest way, but not 100% the suggested way.
More proper way with details if you have time
Instead, you can add @EnableConfigurationProperties({Config1.class, Config2.class}) in a @SpringBootTest, to inject only some of the configuration properties class into the context, to avoid injection overhead.
It would be like:
//@RunWith(SpringRunner.class) // for JUnit4 in Spring
@ExtendWith(SpringExtension.class) // for JUnit5 in Spring. 
@SpringBootTest
@EnableConfigurationProperties({
 ResourcesConfigProperties.class,
})
@Data
public class ConfigsTest {
 @Autowired
 private ResourcesConfigProperties resourceConfigProperties;
 ...
}
Better yet, you can use @SpringBootTest(classes={}): classes within {} are those you want the application context of @SpringBootTest to manage(creation, initialization, loading properties from yaml files, and so on). Then you don't have to load all the context, but only part of it.
You can group all classes of @ConfigurationProperties in one class of @Configuration, and put it in the classes={} of @SpringBootTest, instead of repeating this list of @ConfigurationProperties everywhere. Something like:
//@RunWith(SpringRunner.class) // for JUnit4 in Spring
@ExtendWith(SpringExtension.class) // for JUnit5 in Spring. 
@SpringBootTest(classes = {
 TestConfiguration.class
})
@Data
public class ConfigsTest {
 @Autowired
 private ResourcesConfigProperties resourceConfigProperties;
 ...
}
TestConfiguration.java:
@EnableConfigurationProperties({
 ResourcesConfigProperties.class,
})
@Configuration
public class TestConfiguration {
}
 1 Comment
@NoArgsConstructor as well as @AllArgsConstructor to the mapping class; that bite me again. And, the fields cannot be declared final, nor can you use @Builder on that class. It should not be declared as @Component, neither. @Data is needed, of course.You need to add ResourcesConfigProperties to your EnableConfigurationProperties annotation in the main spring boot class, this will load and create a bean out of the ResourceConfigProperties for you
You could also add @Component to your ResourceConfigProperties if you do not want to add it to the EnableConfigurationProperties annotation.
When using the SpringBootTest or any slice test it will use whatever is annotated on, or beans defined within the main SpringBootApplication within the test context.
Comments
You also need to annotate ResourcesConfigProperties class with @Configuration as below, otherwise it will not create a bean of this class in the spring container.
@Configuration
@ConfigurationProperties(prefix = "files")
public class ResourcesConfigProperties {
 private String huge;
 /**
 * @return the huge
 */
 public String getHuge() {
 return huge;
 }
 /**
 * @param huge the huge to set
 */
 public void setHuge(String huge) {
 this.huge = huge;
 }
}
 
@ComponenttoResourcesConfigPropertiesbecause@ConfigurationPropertiesdoes not import any of the spring annotations that create a bean.@ConfigurationtoResourcesConfigPropertiesclass otherwise it will not create a bean of this class in the spring container and@Autowiredwill not work.