Search code examples
javaspring-bootjunitjunit5spring-boot-test

Junit5 Test not able to inject dependency but running application normally can inject it


Currently, I am working in a project where I created @Entity Class , @Repository for storing some information. I created a service just like other existing ones and then tried that @Service annotated class to be injected at Controller annotated with @RestController. It works perfectly and was able to run the application normally without issues i.e no injection issues.

Now when I am trying to run the tests of my existing project, it fails as my service was unable to be injected into the controller class. Getting this error :

No qualifying bean of type 'com.example.service.exampleService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

Now I tired field and constructor injection, getting same issue every time, but I am following same patterns previously used by the project. I am quite sure the autowiring and other stuffs are properly done else the endpoints I created would not have worked.

My question is why this can happen ? i.e it works when running as spring boot application but not in test context. I tried to follow other posts but I cant follow them as most were fore Junit4

Currently I am using Junit5.

Here is how my test classes looks like

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;


@WebMvcTest
@AutoConfigureMockMvc(addFilters = false)
@ExtendWith(MockitoExtension.class)
public class sampleTest{

 @Test
    public void sampletesting() throws Exception{
      ...
    }
}

Here are my dependencies I am using and the Spring boot version :

    plugins {
        id 'org.springframework.boot' version '2.3.0.RELEASE'
        id 'io.spring.dependency-management' version '1.0.9.RELEASE'
        id 'java'
        id 'jacoco'
    }
 testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    testImplementation('org.mockito:mockito-core:3.5.13')
    testImplementation('org.mockito:mockito-inline:3.5.13')
    testImplementation('org.mockito:mockito-junit-jupiter:3.5.13')

I am using Java 11


Solution

  • @WebMvcTest is used in cases where you want to load only a specific part of all the available beans in the applications: web controllers (and some other web-mvc related classes, like converters, etc). It won't load any service and this is done intentionally:

    Using @WebMvcTest implies that you want to test the controller code (all the annotations are defined correctly, etc.). Usually in this kind of tests you'll call controller method, with something called mockMvc and will check for expected result

    You can read here for example about this kind of tests. Usually the controllers will have injected services, in this case you should use @MockBean on the service.

    So strictly speaking this is the reason for the failure.

    Now in your case, if you want to load the whole application context, consider using @SpringBootTest. You'll also have to think about the database that should be accessible during the test.