2012-09-21 12 views
8

Utilizzo di Spring 3.1.2, JUnit 4.10.0 e piuttosto nuovo per entrambe le versioni. Sto avendo il problema che non riesco a far funzionare l'autowiring basato su annotazione.Autowiring non funziona in Primavera 3.1.2, JUnit 4.10.0

Di seguito sono riportati due esempi, quello senza annotazioni, che funziona correttamente. E il secondo usando l'annotazione, che non funziona, e non ne trovo il motivo. Ho seguito i campioni del test mvc di primavera più o meno.

lavoro:

package com.company.web.api; 
// imports 

public class ApiTests { 

    @Test 
    public void testApiGetUserById() throws Exception { 
     ApplicationContext ctx = new ClassPathXmlApplicationContext("/com/company/web/api/ApiTests-context.xml"); 
     UserManagementService userManagementService = (UserManagementService) ctx.getBean("userManagementService"); 
     ApiUserManagementController apiUserManagementController = new ApiUserManagementController(userManagementService); 
     MockMvc mockMvc = standaloneSetup(apiUserManagementController).build(); 

     // The actual test  
     mockMvc.perform(get("/api/user/0").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); 
    } 
} 

mancanza, perché userManagementService è nullo, non farsi autowired:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration  // should default to ApiTests-context.xml in same package 
public class ApiTests { 

    @Autowired 
    UserManagementService userManagementService; 

    private MockMvc mockMvc; 

    @Before 
    public void setup(){ 
     // SetUp never gets called?! 
    } 

    @Test 
    public void testGetUserById() throws Exception { 

     // !!! at this point, userManagementService is still null - why? !!!  

     ApiUserManagementController apiUserManagementController 
      = new ApiUserManagementController(userManagementService); 

     mockMvc = standaloneSetup(apiUserManagementController).build(); 

     // The actual test 
     mockMvc.perform(get("/api/user/0").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); 
    } 
} 

Si noti che entrambe le classi di test di cui sopra dovrebbero utilizzare la stessa configurazione contesto, e l'userManagementService è definito lì.

ApiTests-context.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xmlns:jee="http://www.springframework.org/schema/jee" 
     xsi:schemaLocation=" 
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
      http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd 
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
     <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
     <property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=utf8"/> 
     <property name="username" value="user"/> 
     <property name="password" value="passwd"/> 
    </bean> 

    <!-- Hibernate SessionFactory --> 
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" 
      p:dataSource-ref="dataSource" p:mappingResources="company.hbm.xml"> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
       <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
       <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop> 
      </props> 
     </property> 
     <property name="eventListeners"> 
      <map> 
       <entry key="merge"> 
        <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/> 
       </entry> 
      </map> 
     </property> 
    </bean> 

    <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --> 
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" 
      p:sessionFactory-ref="sessionFactory"/> 

    <!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= --> 

    <context:annotation-config/> 
    <tx:annotation-driven/> 
    <context:mbean-export/> 

    <!-- tried both this and context:component-scan --> 
    <!--<bean id="userManagementService" class="com.company.web.hibernate.UserManagementServiceImpl"/>--> 
    <context:component-scan base-package="com.company"/> 

    <!-- Hibernate's JMX statistics service --> 
    <bean name="application:type=HibernateStatistics" class="org.hibernate.jmx.StatisticsService" autowire="byName"/> 

</beans> 

e UserManagementService (interfaccia) nonché UserManagementServiceImpl ha la @Service annotazione.

Due domande/osservazioni minori: setup() non viene mai chiamato, anche se ha l'annotazione @Before. Inoltre, ho notato che i miei metodi di test non vengono eseguiti/riconosciuti se non iniziano con il nome 'test', il che non è il caso con tutti gli esempi di test mvc spring che ho visto.

pom.xml:

<dependency> 
     <groupId>org.junit</groupId> 
     <artifactId>com.springsource.org.junit</artifactId> 
     <version>4.10.0</version> 
     <scope>test</scope> 
    </dependency> 

enter image description here

Aggiornamento:

Il problema si verifica solo quando si esegue il test da Maven; è ok quando eseguo il test dal mio IDE (IntelliJ IDEA).

 <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-surefire-plugin</artifactId> 
      <version>2.12.3</version> 
      <configuration> 
       <includes> 
        <include>**/*Tests.java</include> 
       </includes> 
      </configuration> 
     </plugin> 
+0

Cosa succederebbe se si utilizza lo stile di annotazione, con un file di configurazione esplicita chiamato '@ContextConfiguration (" percorso di classe: com/azienda/web/API/ApiTests -context.xml ")' – Ralph

+2

pubblica il contesto completo per favore. anche postare il tuo pom perché sembra che tu stia usando junit 3 in qualche modo? – MikePatel

+0

@ Ralph Provato già, nessuna differenza. @ContextConfiguration (locations = {"classpath: company/com/web/api/ApiTests-context.xml"}) –

risposta

6

L'autowiring non si verifica se non si esegue una scansione dei componenti.

Perché hai commentato nel tuo codice?

<!--<context:component-scan base-package="com.company"/>--> 

Inoltre: junit. Se sei in eclissi puoi semplicemente andare alla vista ad albero delle dipendenze del pom e filtrare su junit. Verifica che stai effettivamente usando quella versione e non inserendo una junit precedente.

Modifica: OK Ho appena controllato la configurazione e sono riuscito a farlo funzionare da questa parte.La mia unica ipotesi può essere che tu sia in qualche modo in esecuzione con un cattivo test runner che sta causando l'uso della junit sbagliata.

Modifica 2 (RISOLTO): Quindi il problema è dovuto al fatto che si sta utilizzando una versione personalizzata di junit. Surefire cerca la libreria junit fornita e non riesce a trovarla. Di conseguenza, il valore predefinito è junit 3, che è ciò che impedisce alla tua app di caricare la configurazione.

Si può esplicitamente specificare il provider personalizzato come

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-surefire-plugin</artifactId> 
    <version>2.12.3</version> 
    <dependencies> 
     <dependency> 
     <groupId>org.apache.maven.surefire</groupId> 
     <artifactId>surefire-junit47</artifactId> 
     <version>2.12.3</version> 
     </dependency> 
    </dependencies> 
    </plugin> 

ma ho scoperto che non funziona bene con i pronti contro termine personalizzati. Se possibile, suggerirei di usare la versione standard di junit.

+0

Avevo testato sia la scansione dei componenti sia il caricamento manuale del bean. Non farebbe lo stesso? Ma comunque, non funziona in nessun modo, anche quando utilizzo la scansione dei componenti. Non sono in Eclipse, sono in IntelliJ IDEA. C'è anche un albero delle dipendenze, e mi sta mostrando org.junit: com.springsource.org.junit: 4.10.0 –

+0

Ho cambiato di nuovo le domande/codice in Component-Scan (non più commentato) di nuovo. Come già detto, l'ho provato anche prima, ma ancora senza successo). –

+0

Io uso SpringJUnit4ClassRunner - intendi questo? È quello che usano ovunque http://rstoyanchev.github.com/spring-31-and-mvc-test/#26 –

0

Provare la configurazione del contesto specifica, ad es.

@ContextConfiguration(locations = {"/file1.xml", "/file2.xml" }) 

(solo mostrando come questo può essere utilizzato con più file quando necessario - uno può essere sufficiente)

Edit: avete abilitato AutowiredAnnotationBeanPostProcessor come accennato qui? http://www.mkyong.com/spring/spring-auto-wiring-beans-with-autowired-annotation/

+0

Provato, nessuna differenza, vedere la domanda aggiornata sopra. –

0

Ho avuto lo stesso problema. Il mio @Autowire funzionava all'interno del mio IDE (SpringSource STS) ma non riusciva a caricare il contesto dell'applicazione mentre stavo usando Maven per compilare dalla riga di comando.

Il problema riguardava le mie dipendenze in pom.xml. Stavo usando la versione Spring di JUnit che ha causato l'errore. Penso che questa sia la causa principale del post originale. Non ho dovuto codificare alcun plugin Maven per farlo funzionare.

ho cambiato

<dependency> 
    <groupId>org.junit</groupId> 
    <artifactId>com.springsource.org.junit</artifactId> 
    <version>4.7.0</version> 
</dependency> 

a

<dependency> 
    <groupId>junit</groupId> 
    <artifactId>junit</artifactId> 
    <version>4.10</version> 
</dependency> 
Problemi correlati