5

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)
Nuñito Calzada
  • 4,394
  • 47
  • 174
  • 301

4 Answers4

5

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.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
4

This fix my problem:

@RunWith(SpringRunner.class)
@SpringBootTest(classes =  TdkApplication.class)
public class SigfoxRestApiServiceTests {
.
}
Nuñito Calzada
  • 4,394
  • 47
  • 174
  • 301
1

Try adding @SpringBootTest to the test class:

@SpringBootTest
@RunWith(SpringRunner.class)
public class TdkRestApiServiceTests {
   ...
}
ognjenkl
  • 1,407
  • 15
  • 11
0

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.

Ashraf Sarhan
  • 1,507
  • 16
  • 21
  • Didn't seem enough somehow, wasn't finding my beans...till I added more like `@Import({ MyClass1.class, MyConfigurationClass2.class }` – rogerdpack Oct 12 '20 at 21:03
  • I think it depends on where your classes are located, in my case all classes were in the same base package. – Ashraf Sarhan Oct 22 '20 at 13:52