Nuñito Calzada
Nuñito Calzada

Reputation: 2056

Junit Test in Spring Boot does not inject the service

I have a basic SpringBoot app. using Spring Initializer, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file.

I have this service:

@Service
public class TdkRestApiService {
    ...
}

that I want to test:

@ContextConfiguration(classes={TdkApplicationConfig.class, TdkDevelopmentConfig.class}) 
@RunWith(SpringRunner.class)
public class TdkRestApiServiceTests {


    /**
     * The object being tested.
     */
    @Autowired
    TdkRestApiService tdkRestApiService;

    @Test
    public void getCallbacksByDeviceTypeTest () throws IOException {

        tdkRestApiService.getCallbacksByDeviceType("2", "3");

    }
}

but I got an error:

ERROR o.s.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@dd3b207] to prepare test instance [com.tdk.backend.service.TdkRestApiServiceTests@6db9f5a4]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.tdk.backend.service.TdkRestApiServiceTests': Unsatisfied dependency expressed through field 'tdkRestApiService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.tdk.backend.service.TdkRestApiService' 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)

Upvotes: 5

Views: 12168

Answers (4)

ognjenkl
ognjenkl

Reputation: 1477

Try adding @SpringBootTest to the test class:

@SpringBootTest
@RunWith(SpringRunner.class)
public class TdkRestApiServiceTests {
   ...
}

Upvotes: 1

Ashraf Sarhan
Ashraf Sarhan

Reputation: 1687

There is a neat solution by creating a TestConfig.class like the following:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class TestConfig {

}

Then, you can add it to your test class with the @Autowired components like the following:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfig.class)
public class Test { 

   @Autowired
   private Component component;

}

After that, you will be able to use Spring components inside your test class.

Upvotes: 0

Nuñito Calzada
Nuñito Calzada

Reputation: 2056

This fix my problem:

@RunWith(SpringRunner.class)
@SpringBootTest(classes =  TdkApplication.class)
public class SigfoxRestApiServiceTests {
.
}

Upvotes: 4

davidxxx
davidxxx

Reputation: 131326

Here :

@ContextConfiguration
@RunWith(SpringRunner.class)
public class TdkRestApiServiceTests {

You don't specify the classes attribute of the ContextConfiguration annotation.

You should set this attribute with your root Spring configuration class that sets all your configuration and particularly the TdkRestApiService bean.
For example if your root Spring configuration class is MyConfig, you could specify it :

@ContextConfiguration(classes = MyConfig.class)
@RunWith(SpringRunner.class)
public class TdkRestApiServiceTests {

You can have more information on the Spring documentation discussing of detecting test configuration.

Below an extract :

If you’re familiar with the Spring Test Framework, you may be used to using @ContextConfiguration(classes=…​) in order to specify which Spring @Configuration to load. Alternatively, you might have often used nested @Configuration classes within your test.

Upvotes: 5

Related Questions