Home > OS >  How to use @Autowired in SpringBoot unit test
How to use @Autowired in SpringBoot unit test

Time:07-08

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

  • Related