Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why unit testing with Spring 3.1 WebMvcConfig fails?

Tags:

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() {} } 
like image 410
Sanghyun Lee Avatar asked Jul 03 '12 05:07

Sanghyun Lee


People also ask

What are the limitations of unit testing?

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.

Does Spring support unit testing?

Spring includes a number of classes that can help with unit testing. They fall into two categories: General Testing Utilities. Spring MVC Testing Utilities.


2 Answers

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 {     //... } 
like image 83
Steve Avatar answered Mar 13 '23 11:03

Steve


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() {} } 
like image 29
Slava Semushin Avatar answered Mar 13 '23 09:03

Slava Semushin