为什么使用Spring 3.1 WebMvcConfig进行单元测试会失败?

2022-09-02 01:33:39

从 Spring 3.1 开始,由于@Enable* 注释,我们可以更轻松地使用 JavaConfig。

所以我做了一个WebConfig来设置WebMvc配置,并试图测试它。但是,如果我扩展WebMvcConfigurerAdapter或WebMvcConfigurationSupport与WebConfig,则单元测试会因为缺少ServletContext而失败。代码和消息如下所示。

网络配置.java

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurationSupport {}

测试.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=WebConfig.class)
public class TestFail {
    @Test
    public void test() {}
}

消息

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

如何正确地对WebConfig进行单元测试?

编辑

正如Garcia所说,这个错误在Spring 3.2.0.RC1中得到了修复。

只需在测试类中添加@WebAppConfiguration注释即可。

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes=WebConfig.class)
public class TestFail {
    @Test
    public void test() {}
}

答案 1

正如Guido之前提到的,这个问题已经从3.2开始解决了。以下是有关如何利用新的测试改进的详细信息。要确保为您的测试加载 servlet 上下文,您需要使用上下文加载程序对测试进行注释并定义为上下文加载程序,如下所示:@WebAppConfigurationAnnotationConfigWebContextLoader

@RunWith(SpringJUnit4ClassRunner.class)    
@WebAppConfiguration
@ContextConfiguration(
    classes = MyWebConfig.class, 
    loader = AnnotationConfigWebContextLoader.class)
public class MyTest {
    //...
}

答案 2

如果需要注释,那么我建议将您的配置拆分为bean定义,这些定义将用于单元测试以及应用程序和框架使用的其他配置。在这种情况下,应用程序将同时导入配置,单元测试将仅导入一个配置。@EnableWebMvcServletContext

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() {}
}

推荐