Подтвердить что ты не робот

Почему модульное тестирование с помощью Spring 3.1. Ошибка WebMvcConfig?

Из Spring 3.1 мы можем проще использовать JavaConfig благодаря @Enable * аннотациям.

Итак, я создал WebConfig для настройки конфигурации WebMvc и попытался проверить его. Но если я расширяю WebMvcConfigurerAdapter или WebMvcConfigurationSupport с помощью WebConfig, то unit test выходит из строя из-за отсутствия ServletContext. Код и сообщения выглядят ниже.

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

Сообщение

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

Как unit test WebConfig правильно?

Edit

Как сказал Гарсиа, эта ошибка исправлена ​​в Spring 3.2.0.RC1.

Просто добавьте аннотацию @WebAppConfiguration в тестовый класс.

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

Ответ 1

В Spring 3.1 есть ошибка, вы можете найти ответ в этих двух проблемах:

Пожалуйста, сообщите нам, если вы найдете обходной путь для Spring 3.1, если нет, мы должны подождать, пока там не появится 3.2. Я должен сказать, что я только что попробовал его с Spring 3.2.0.M2, и он по-прежнему не работает для меня.

Ответ 2

Как упоминалось ранее Гвидо, это было решено с 3.2. Ниже приведены подробные сведения о том, как использовать преимущества новых улучшений тестов. Чтобы убедиться, что для теста загружен контекст сервлета, вам необходимо аннотировать свой тест с помощью @WebAppConfiguration и определить AnnotationConfigWebContextLoader в качестве загрузчика контекста, как показано ниже:

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

Ответ 3

Если аннотация @EnableWebMvc требует ServletContext, я предлагаю разделить конфигурацию на beans определения, которые будут использоваться в модульных тестах и ​​другой конфигурации, которые используются приложением и каркасом. В этом случае приложение будет импортировать обе конфигурации, а модульные тесты будут импортировать только один.

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

Ответ 4

Еще одна рекомендация, которую я должен был бы использовать spring-test-mvc, которая внутренне создает макет контекста сервлета для тестов Контроллера для работы.

Если вы хотите продолжить свой подход, вам может понадобиться создать свой собственный Spring Контекстный загрузчик, который дополнительно инициализирует контекст сервлета Mock - вдоль этих строк: http://tedyoung.me/2011/02/14/spring-mvc-integration-testing-controllers/, Из Spring -test-mvc source