I am writing junits for a rest controller. I want only minimal context to be loaded which is related to the controller and I think that is how @WebMvcTest
loads the context. But the junit is loading complete Spring context and it is failing as some of the beans can not be created.
I have searched and read through many questions on stackoverflow and none of the solutions worked to exclude specific configuration. How can I load a minimal context when writing junits for controllers? Or is there any way to exclude some configuration classes? I am using Spring-boot 2.2.2.RELEASE, Java 8 and Junit 4.
Junit (where I have tried to exclude loading of some beans and configurations but it doesn’t work):
@RunWith(SpringRunner.class) @WebMvcTest(controllers = OrderController.class, excludeFilters = {@Filter(classes = Configuration.class), @Filter(type = FilterType.REGEX, pattern = "com\.foo\..*")}) @TestPropertySource(properties = { "spring.cloud.config.server.bootstrap:false" }) public class OrderControllerTest { @MockBean private OrderService orderService; @Autowired private MockMvc mockMvc; @Test public void test() throws Exception { mockMvc.perform(get("/internal/order/123")); // Further code to verify the response } }
Controller
@Slf4j @Validated @RestController @RequestMapping("/internal") public class OrderController { @Autowired private OrderService orderService; @GetMapping(value = "/order/{orderId}", produces = { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<RegularContributionOrder> retrieveRegularContributionOrder(@NotNull @PathVariable("orderId") String orderId) throws OrderNotFoundException { RegularContributionOrder order = orderService.retrieve(orderId); return new ResponseEntity<RegularContributionOrder>(order, HttpStatus.OK); } }
Configuration class which I want to exclude from context loading
@Slf4j @Configuration @EnableAspectJAutoProxy @ImportResource({ "classpath:spring/service-config-one.xml", "classpath:spring/service-config-two.xml" }) public class OrderServiceConfig { @Bean public MessageSource messageSource() { ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); messageSource.setBasename("classpath:resourcebundles/error-messages.properties"); messageSource.setDefaultEncoding("UTF-8"); return messageSource; } @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); return mapper; } }
Spring boot main class:
@EnableJms @EnableAspectJAutoProxy @ComponentScan(basePackages = { "com.foo.services", "com.bar" }) @SpringBootApplication(exclude = { SomeConfiguration.class}) public class BootApplication extends SpringBootServletInitializer { @Override protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) { return application.sources(BootApplication .class); } public static void main(final String[] args) { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); SpringApplication.run(BootApplication.class, args); } }
Advertisement
Answer
Your use of @ComponentScan
has disabled the filters that are used by @WebMvcTest
to limit the types of components that are found by scanning.
You should remove @ComponentScan
from your main application class and use the basePackages
attribute on @SpringBootApplication
instead.
You should also move @EnableJms
and @EnableAspectJAutoProxy
to a separate @Configuration
class so that they are not enabled when using @WebMvcTest
. Alternatively, you may be able to remove them entirely as they are covered by Spring Boot’s auto-configuration.