From Spring 3.1, we can use JavaConfig more easily thanks to @Enable* annotations.
So I made a WebConfig to set WebMvc configuration, and tried to test it. But if I extends WebMvcConfigurerAdapter or WebMvcConfigurationSupport with WebConfig the unit test fails because of lack of ServletContext. The code and messages look like below.
WebConfig.java
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurationSupport {}
Test.java
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=WebConfig.class) public class TestFail { @Test public void test() {} }
Message
java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) ... 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:253) at com.zum.news.comments.web.WebConfig$$EnhancerByCGLIB$$8bbfcca1.CGLIB$defaultServletHandlerMapping$10(<generated>) at com.zum.news.comments.web.WebConfig$$EnhancerByCGLIB$$8bbfcca1$$FastClassByCGLIB$$19b86ad0.invoke(<generated>) at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:215) at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:280) at com.zum.news.comments.web.WebConfig$$EnhancerByCGLIB$$8bbfcca1.defaultServletHandlerMapping(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:149) ... 41 more
How to unit test the WebConfig properly?
Edit
As Garcia said, this bug is fixed in Spring 3.2.0.RC1.
Just add @WebAppConfiguration annotation in the test class.
@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes=WebConfig.class) public class TestFail { @Test public void test() {} }
Limitations of Unit Testing Unit testing cannot detect integration or interfacing issues between two modules. It cannot catch complex errors in the system ranging from multiple modules. It cannot test non-functional attributes like usability, scalability, the overall performance of the system, etc.
Spring includes a number of classes that can help with unit testing. They fall into two categories: General Testing Utilities. Spring MVC Testing Utilities.
As Guido mentioned previously, this has been solved as of 3.2. The following are the details of how to take advantage of the new test improvements. To ensure that a servlet context is loaded for your test, you need to annotate your test with @WebAppConfiguration
and define AnnotationConfigWebContextLoader
as your context loader, as below:
@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration( classes = MyWebConfig.class, loader = AnnotationConfigWebContextLoader.class) public class MyTest { //... }
If @EnableWebMvc
annotation require ServletContext
then I suggest to split your config to beans definitions which will be used in unit tests and other configuration which used by application and framework. In this case application will import both configs and unit tests will import only one.
BeansConfig.java
:
@Configuration public class BeansConfig { @Bean MyBean myBean() { return new MyBean() } }
WebConfig.java
:
@Configuration @EnableWebMvc @Import(BeansConfig.class) public class WebConfig extends WebMvcConfigurationSupport {}
TestFail.java
:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=BeansConfig.class) public class TestFail { @Test public void test() {} }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With