2012-07-03 16 views
22

Dalla primavera 3.1, possiamo usare JavaConfig più facilmente grazie alle annotazioni @Enable*.Perché il test dell'unità con Spring 3.1 WebMvcConfig non riesce?

Così ho creato una WebConfig per impostare la configurazione WebMvc e ho provato a testarla. Ma se estendo WebMvcConfigurerAdapter o WebMvcConfigurationSupport con WebConfig il test dell'unità fallisce a causa della mancanza di ServletContext. Il codice e i messaggi sono riportati di seguito.

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

Messaggio

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 

Come unità di testare il WebConfig correttamente?

Modifica

Come ha detto Garcia, questo bug è fissato in primavera 3.2.0.RC1.

Basta aggiungere l'annotazione @WebAppConfiguration nella classe di test.

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

Non capisco come questa domanda ha così pochi voti. Suppongo che ci siano persone là fuori che provano a fare test di integrazione con le sottigliezze di Spring 3.1 ... –

+1

La domanda era esattamente quello che stavo cercando e la risposta è inclusa nella sezione "Modifica" –

risposta

6

C'è un bug nella primavera del 3.1, è possibile trovare la risposta a queste due questioni:

Per favore fateci sapere se trovate una soluzione alternativa per Spring 3.1, in caso contrario dobbiamo aspettare fino a quando 3.2 è disponibile. Devo dire che l'ho appena provato con Spring 3.2.0.M2 e non funziona ancora per me.

+1

3.2.0.RC1 è là fuori e il bug è corretto. Dovrebbe funzionare anche su 3.2.0.M2, a condizione di annotare le classi di test con @WebAppConfiguration. –

7

Se @EnableWebMvc annotazione richiede ServletContext allora vi consiglio di dividere la vostra configurazione per le definizioni fagioli che verranno utilizzate nei test unitari e altre configurazioni che hanno usato per applicazione e il quadro. In questo caso l'applicazione importa sia le configurazioni che i test unitari ne importeranno solo una.

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

In realtà, questo è quello che sto facendo adesso. Mi chiedo perché il test unitario fallisce. Era ok quando configurato con XML in Spring 3.0. –

12

Come già detto da Guido, questo è stato risolto al punto 3.2. Di seguito sono riportati i dettagli su come sfruttare i nuovi miglioramenti del test. Per garantire che un contesto servlet viene caricato per il test, è necessario annotare il test con @WebAppConfiguration e definire AnnotationConfigWebContextLoader come vostro contesto loader, come di seguito:

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

Puoi spiegare come viene caricato il contesto di applicazione in questi casi di test. Apprezzo che la classe MyWebConfig sostituisca il file servlet-context.xml per inizializzare l'app Web, ma se il nostro controller dipende da altri bean da iniettare come è fatto. In altri esempi un 'location = classparth = context.xml' è passato a ContextConfiguration - è ancora possibile nell'esempio sopra? – emeraldjava

+1

Nella classe '@ Configuration'. Questo definisce quali percorsi di classe devono essere scansionati per i bean annotati come '@ Component',' @ Controller', '@ Service', ecc. Può anche usare l'annotazione 'Import' per importare un contesto XML. Puoi creare le classi '@ Configuration' specificatamente per i tuoi test, se lo desideri. – Steve

+0

Grazie. Nella nostra vera applicazione web, ho un ContextLoaderListener nel file web.xml che carica un contextConfigLocation = '/ WEB-INF/applicationContext.xml'. Per il mio caso di test, penso che tu stia suggerendo di aggiungere l'istruzione Importa alla mia classe WebAppConfig ma questo non significherebbe che il contesto viene caricato due volte se la vera webapp. Mi sarei aspettato che il codice della classe di test facesse qualcosa per caricare applicationContext.xml piuttosto che leggere la classe di configurazione. – emeraldjava

Problemi correlati