I've a @RestController
which has only one dependency in field @Autowire
that dependency is @component, that component Class definition has some autowired fields which are @service and those services have some @repositories.
In this whole flow I've kafka, Quartz, Cassandra and DB2 So when I was creating a Unit test case for my controller, I dont want to setup whole application. so I decided to use @webMvcTest and used @MockBean on my only one dependency of controller class.
But my Test is throwing and exception because its trying to create a Dao bean, which is marked as @repository.
@ActiveProfiles("test")
@WebMvcTest(controllers = MyControllerTest .class)
class MyControllerTest {
@MockBean
MyControllerDependency dependency;
@Autowired
MockMvc mockMvc;
@Test
void test_something() throws Exception {
assert(true);
}
}
Here is oversimplified version of code
@Component
class MyControllerDependency {
@AutoiWired
MyCustomService service;
}
@Service
class MyCustomService{
@Autowired
MyCustomDao dao;
}
@Repository
class MyCustomDao{
@Autowired
private JdbcTemplate template;
}
I'm getting following exception in test.
Exception
***************************
APPLICATION FAILED TO START
***************************
Description:
Field template in com.....MyCustomDao` required a bean of type 'org.springframework.jdbc.core.JdbcTemplate' that could not be found.
Question is, When I'm using @WebMvcTest
slice and already mocking the only required dependency MyControllerDependency
then why spring test context is trying to load MyCustomDao
which is annotated as @Repository
.
I can do integration testing with SpringbootTest
& AutoconfigureMockMVC
, but for writing Junit test just for controller, I need to use WebMvcTest
slice. which is creating a problem.
Do you have any @ComponentScan("...")
annotation active on your @SpringBootApplication
?
As described in Spring Boot Reference Documentation:
Another source of confusion is classpath scanning. Assume that, while you structured your code in a sensible way, you need to scan an additional package. Your application may resemble the following code:
@SpringBootApplication
@ComponentScan({ "com.example.app", "com.example.another" })
public class MyApplication {
// ...
}
Doing so effectively overrides the default component scan directive with the side effect of scanning those two packages regardless of the slice that you chose. For instance, a @DataJpaTest seems to suddenly scan components and user configurations of your application. Again, moving the custom directive to a separate class is a good way to fix this issue.
One solution is to create a seperate @Configuration
that is annotated with @ComponentScan
. When creating a @WebMvcTest
the configuration (and its component scan is ignored).
@Configuration
@ComponentScan("com.example.another")
public class DbConfig {
}