Почему модульное тестирование с помощью 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() {}
}
Ответы
Ответ 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