问题
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);
}
}
回答1:
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 {
}
回答2:
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.
回答3:
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;
}
}
来源:https://stackoverflow.com/questions/52605568/spring-boot-configurationproperties-not-satisfied-on-test