Reputation: 6920
I have a spring boot application yielding numerous controllers and my goal is to create an integration test for a specific one. I read that we can achieve a test slice with the @WebMvcTest
annotation that loads only what is necessary to deploy the target controller, is this assumption correct? Here is my test:
@RunWith(SpringRunner.class)
@WebMvcTest(
controllers = {DummyController.class},
)
public class DummyControllerIT {
@Autowired
private MockMvc mockMvc;
...
Unfortunately the execution attempts to deploy other controllers/services/repositories that have no relation to the target Controller, which forces me use @MockBean
on each of them. I was under the impression that @WebMvcTest
would spare me from having an extensive listing of declared controllers/services/repositories with the @MockBean
annotation, am I wrong?
If I misinterpreted this and I am expected to use @MockBean
on unrelated parts of the application, then why is it better to use @WebMvcTest
instead of @SpringBootTest
? On the other hand, if I interpreted it correctly what am I missing?
Not sure if it is related but this is my initialiser:
@ComponentScan(scopedProxy = ScopedProxyMode.INTERFACES)
@SpringBootApplication
@EnableTransactionManagement
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableScheduling
@EnableCaching
@EnableJpaAuditing
@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
public class Application extends SpringBootServletInitializer {
@Autowired
private Environment env;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
@Bean
@Primary
public TaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(Integer.parseInt(Objects.requireNonNull(env.getProperty("coreThreadPoolSize"))));
executor.setMaxPoolSize(Integer.parseInt(Objects.requireNonNull(env.getProperty("maxThreadPoolSize"))));
executor.initialize();
return executor;
}
}
Thank you for your help.
Upvotes: 0
Views: 1253
Reputation: 116051
@WebMvcTest
works by disabling full auto-configuration of your application and also filtering its component scanning so that only the parts that are needed are configured. Your main class, Application
, is enabling auto-configuration (via @SpringBootApplication
) but is also explicitly enabling component scanning as well as caching, security, JPA repositories, etc. @WebMvcTest
doesn't switch off these explicitly enabled pieces so you're left having to mock things.
This problem and the recommended way to avoid it is described in the reference documentation. In short, you should move the various @Enable…
annotations to separate @Configuration
classes that are picked up by component scanning. You may also want to review the need for some of them. For example, @EnableTransactionManagement
is covered by auto-configuration.
Your use of @ComponentScan
is also problematic as it switches off the filtering that @WebMvcTest
requires. Moving it away from the @SpringBootApplication
-annotated class should fix this part of the problem.
Upvotes: 5