56

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 {
...

The issue seems to come from 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) })
public class BaseTestConfiguration {

}

I systematically 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$$bb4ceb44.CGLIB$defaultServletHandlerMapping$22(<generated>)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$bb4ceb44$$FastClassByCGLIB$$368bb5c1.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$$bb4ceb44.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

I am not sure how to get around this issue. Somehow Spring is looking for a ServletContext when I run the test and I get the above exception...

balteo
  • 20,469
  • 52
  • 196
  • 362

4 Answers4

140

One of your @Configuration classes is obviously annotated with @EnableWebMvc. That's how DelegatingWebMvcConfiguration ends up in your stack trace, since it is imported by @EnableWebMvc.

So although you think you don't need a WebApplicationContext (and hence a ServletContext), you in fact do need it simply because you are loading an application context with @EnableWebMvc.

You have two options:

  • Compose the configuration classes for your integration test so that you are not including the web-related configuration (i.e., the @Configuration class(es) annotated with @EnableWebMvc).
  • Annotate your test class with @WebAppConfiguration as suggested in other comments above.

Regards,

Sam (author of the Spring TestContext Framework)

Sam Brannen
  • 24,249
  • 2
  • 75
  • 114
  • I tried to go for the first option you kindly suggested by excluding the @EnableWebMvc-annotated class with an exclude filter i.e. with an filtertype=assignable type but to no avail... – balteo Feb 03 '14 at 10:49
  • 1
    Please also note that I do not include the `@Configuration` class annotated with `@EnableWebMvc` in the above test. It is being picked up by the `@ComponentScan` in BaseTestConfiguration... – balteo Feb 03 '14 at 11:00
  • Any tips for the case where this is happening on spring-boot:run (my tests are running fine)? – Aaron Zeckoski Jul 09 '14 at 12:21
  • Sounds like a completely different question to me. Ask a new one and tag it spring-boot? – Dave Syer Jul 11 '14 at 16:21
  • 6
    Ensure that you are loading the context with an AnnotationConfigWebContextLoader (if using config classes), like this: `@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = {ConfigClass.class})` – Marco Ferrari Sep 29 '14 at 11:17
  • Same issue! But here is how mycase was (for future reference) : in the TestConfig I had @ComponentScan(basePackages="app") and in app package there was a config file which had @EnableWebMvc in it ! – Anand Rockzz Jan 06 '15 at 07:00
  • @ferrarimarco, you do _not_ need to declare `AnnotationConfigWebContextLoader`. It is enabled by default whenever you declare the `classes` attribute of `@ContextConfiguration`. See the "_Context configuration with annotated classes_" section of the testing chapter in the Spring reference manual for details: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#testcontext-ctx-management-javaconfig – Sam Brannen Feb 26 '15 at 01:53
  • @SamBrannen you are right. I was forcing `AnnotationConfigContextLoader` in a superclass. This behaviour is described in the documentation: _If not specified, the loader will be inherited from the first superclass that is annotated with `@ContextConfiguration` and specifies an explicit loader. If no class in the hierarchy specifies an explicit loader, a default loader will be used instead._ – Marco Ferrari Jun 01 '15 at 18:03
38

It seems like you are missing

@WebAppConfiguration

from your test class.

The documentation states

The resource base path is used behind the scenes to create a MockServletContext which serves as the ServletContext for the test’s WebApplicationContext.

Typically a Servlet container would provide the ServletContext. Since you are in a testing environment, you need a fake. @WebAppConfiguration provides that.

Sotirios Delimanolis
  • 252,278
  • 54
  • 635
  • 683
11

For you to instantiate the Servlet context, you would have to use the annotation.

@WebAppConfiguration

A class-level annotation that is used to declare that the ApplicationContext loaded for an integration test should be a WebApplicationContext. The mere presence of @WebAppConfiguration on a test class ensures that a WebApplicationContext will be loaded for the test, using the default value of "file:src/main/webapp" for the path to the root of the web application (i.e., the resource base path). The resource base path is used behind the scenes to create a MockServletContext which serves as the ServletContext for the test’s WebApplicationContext.

Hrishikesh
  • 1,983
  • 1
  • 14
  • 24
0

I was getting a similar error but whilst running the application normally rather than trying to run tests.

It turns out if you're making use of a custom PermissionEvaluator then you need to declare it in a separate @Configuration class to the one with your main Spring security configuration in.

See: How do I add method based security to a Spring Boot project?

There is also an open Github issue: https://github.com/spring-projects/spring-boot/issues/4875

Community
  • 1
  • 1
Robert Hunt
  • 6,348
  • 3
  • 34
  • 42