I am trying to unit test (using JUnit5 jupiter) a class developed in Java with Spring Boot that I would like to use the @Autowired annotation for convenience.
A very simplified version of it is as follow:
import org.springframework.stereotype.Component;
@Component
public class Demo {
public String get() {
return "hello";
}
}
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig
class DemoTest {
@Autowired private Demo sut;
@Test
void Test() {
Assertions.assertEquals("hello", sut.get());
}
}
When I run the test this error occurs:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.example.demo.DemoTest': Unsatisfied dependency expressed through field 'sut'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.Demo' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:659)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:417)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
...
How to prevent it? To be noted: for this test, I do not want to start the full application using @SpringBootTest
Thanks,
CodePudding user response:
Usually when you use @ContextConfiguration
(which is a significant part of the stereotype @SpringJUnitConfig
annotation) you should specify the configuration class from which the "Demo" component will be resolved.
Otherwise spring won't know which classes to load.
So you should basically create a configuration class (annotated with @Configuration
) And specify what do you want to load there, for example with @ComponentScan
Haven't tested it but something like this should work:
@SpringJUnitConfig(MyTestConfig.class)
public class MyTest {
@Autowired Demo sut;
public void test() {... sut.doSomething(...); ...}
}
@Configuration
@ComponentScan(...) // here you should specify how to
// load the Demo class and maybe other classes as well
public class MyTestConfig {
}
Of course if instead of @Component
you already use Java Config and define Demo
class there you won't need to create this auxiliary MyTestConfig
class and can load the configuration with the Demo
class right away