Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot Unit Test a module not detecting an autowired component

we have split our Maven based Spring Boot project into two modules as follows:

ProjectRoot
-SharedModel
-Application
--main
---java
----com....(Application.java)
-----com....(ClassToAutowire.java)
--test
----com....(ApplicationTest.java)
-----com....(ClassToAutowireTest.java)

The test class looks as follows:

@RunWith(SpringRunner.class)
public class ClassToAutowireTest extends BaseTest {

    @Autowired
    private ClassToAutowire classToAutowire;

    @Before
    public void setup() throws IOException {        
    ....
    }

    @Test
    public void someTest() {
        ....
        assertEquals(this.classToAutowire.isSupported(this.message), true);
    }

}

The ClassToAutowire looks like the follows:

@Component
public class ClassToAutowire {

    private ConfigurationService configurationService;

    @Autowired
    public ClassToAutowire(ConfigurationService configurationService) {
        this.configurationService = configurationService;
    }



    ....

}

The Application.java looks as follows:

@SpringBootApplication
@EnableRetry
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

And the ApplicationTest.java looks as follows:

@SpringBootTest
@RunWith(SpringRunner.class)
public class ApplicationTests {

    @Test
    @Ignore
    public void contextLoads() {
        // °º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸
    }
}

When I run this Unit Test, we get the following trace:

    2018-06-27 15:02:37.835 ERROR [                                main] context.TestContextManager.prepareTestInstance(TestContextManager.java:234): Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@57c03d88] to prepare test instance [com.some.package.structure.ClassToAutowireTest@16aa8654]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.some.package.structure.ClassToAutowireTest': Unsatisfied dependency expressed through field 'classToAutowire'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.some.package.structure.ClassToAutowire' 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.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:386)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.some.package.structure.ClassToAutowire' 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.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 27 more

Looks like this problem can be bypassed by adding the annotation @SpringBootTest(classes={ClassToAutowire.class}) below the @RuneWith annotation, but then the unit test seems to load the whole SpringBoot app to run test.

My questions are:

1) Why is this extra annotation needed to workaround the problem? It is supposed to scan the entire Application/main/java/.... (based on Application.java), so why is it not detecting the component?

2) How best to do it, with minimal loading to make unit tests faster?

like image 421
Carmageddon Avatar asked Jun 27 '18 18:06

Carmageddon


People also ask

Why Autowired is not working?

There are several reasons @Autowired might not work. When a new instance is created not by Spring but by for example manually calling a constructor, the instance of the class will not be registered in the Spring context and thus not available for dependency injection.

Is @component required for Autowired?

So the answer is: No, @Autowired does not necessarily mean you must also use @Component . It may be registered with applicationContext. xml or @Configuration+@Bean .

Can we use Autowired in test class?

To check the Service class, we need to have an instance of the Service class created and available as a @Bean so that we can @Autowire it in our test class. We can achieve this configuration using the @TestConfiguration annotation.


1 Answers

Provide your test with @ContextConfiguration(classes = ClassToAutowire.class), then your context will be provided with that class. @SpringBootTest annotation is used in Integration Tests to load full context. With @ContextConfiguration annotation you are able to load only part of context.

like image 61
Pospolita Nikita Avatar answered Oct 05 '22 21:10

Pospolita Nikita