Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing a @EnableWebMvc-annotated class from being picked up by @ComponentScan

I have the following test class:

@ActiveProfiles({ "DataTC", "test" })
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {BaseTestConfiguration.class, DataTestConfiguration.class, JpaConfiguration.class, PropertyPlaceholderConfiguration.class })
public class RegularDayToTimeSlotsTest {

    private static int NUMBER_OF_REGULAR_DAY_TO_TIME_SLOTS_IN_WEEK = 25;

    @Autowired
    private AdvertisementService advertisementService;

    @Test
    public void shouldNotContainSaturdayNorSunday() {
        Set<DayToTimeSlot> regularDayToTimeSlots = advertisementService.retrieveRegularDayToTimeSlots();
        assertThat(regularDayToTimeSlots).onProperty("day").excludes(Day.SATURDAY, Day.SUNDAY);
    }

    @Test
    public void shouldNotContainEveningNorNighttime() {
        Set<DayToTimeSlot> regularDayToTimeSlots = advertisementService.retrieveRegularDayToTimeSlots();
        assertThat(regularDayToTimeSlots).onProperty("timeSlot").excludes(TimeSlot.EVENING, TimeSlot.NIGHTTIME);
    }

    @Test
    public void shouldContainCorrectNumberOfDayToTimeSlots() {
        Set<DayToTimeSlot> regularDayToTimeSlots = advertisementService.retrieveRegularDayToTimeSlots();
        assertThat(regularDayToTimeSlots).hasSize(NUMBER_OF_REGULAR_DAY_TO_TIME_SLOTS_IN_WEEK);
    }
}

This is an integration test that does not need any ServletContext. Here is the BaseTestConfiguration class:

@Configuration
@ComponentScan(basePackages = { "com.bignibou" }, excludeFilters = { @Filter(type = FilterType.CUSTOM, value = RooRegexFilter.class),
        @Filter(type = FilterType.ANNOTATION, value = Controller.class), @Filter(type = FilterType.ANNOTATION, value = ControllerAdvice.class),
        @Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class) })
public class BaseTestConfiguration {

}

This is just a java configuration class that is meant to ensure that all of my application beans are instantiated and wired up correctly but that the class annotated with @EnableWebMvc is not taken into account because I don't need a Servlet context for this integration test.

Unfortunately, however much I try to exclude the Web/Mvc configuration class, it does not work and the @Configuration class annotated with @EnableWebMvc is also picked up.

I get this exception:

Caused by: java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.util.Assert.notNull(Assert.java:112)
    at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.<init>(DefaultServletHandlerConfigurer.java:54)
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:329)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$d1263fa1.CGLIB$defaultServletHandlerMapping$22(<generated>)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$d1263fa1$$FastClassByCGLIB$$e0423f09.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:326)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$d1263fa1.defaultServletHandlerMapping(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
    ... 43 more

Can anyone please help?

like image 585
balteo Avatar asked Jan 28 '26 08:01

balteo


1 Answers

There is in fact a cleaner way to configure such integration tests.

The answer lies in proper separation of concerns, not only at the class level but also at the package level.

It is always recommended that both implementation and configuration classes reside in package hierarchies that allow for proper separation of concerns. Specifically for a web application, it is highly advisable to ensure that web components and web configuration reside in a dedicated 'web' package. For example, you could consider a package hierarchy similar to the following:

  • com.example.domain
  • com.example.service
  • com.example.repository
  • com.example.web

With such a hierarchy you can simplify your component scanning configuration by including only those base packages that are pertinent to the current application or test scenario. By doing this there is typically no need to use exclusion filters for things you don't want. Instead, just specify packages you do want.

By the way, specifying "com.bignibou" as your base package is actually a worst practice since it is all-encompassing.

So give it a shot with explicit package inclusions (instead of excluding @Controller, @ControllerAdvice, etc.) and see if that doesn't make your life easier. ;)

Regards,

Sam

like image 189
Sam Brannen Avatar answered Jan 31 '26 00:01

Sam Brannen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!