2012-03-27 10 views
1

Ich habe ein Open-Source-Projekt unter this Github gehostet. Ich stehe vor einem seltsamen Szenario. Ich habe viele Leute gefunden, die @Autowired Spring-Annotationsarbeiten an ihren Hauptklassen, aber nicht an ihren JUnit-Testklassen durchführen konnten. Mein Problem ist umgekehrt. Ich kann @Autowired erfolgreich in meiner JUnit-Testklasse verwenden, aber wenn ein Test meine Hauptklasse aufruft, werden die Abhängigkeiten dort nicht eingefügt. Hier ist mein Kontext (vereinfachte Version):Spring @Autowired OK auf JUnit, NPE auf Hauptklasse

Login-Klasse:

package net.openrally.restaurant.core.exposure.resource; 

@Path("/login") 
@Component 
@Transactional 
@Singleton 
@Produces("application/json") 
@Consumes("application/json") 
public class Login extends BaseResource{ 

    @Autowired 
    private UserDAO userDAO; 

    @POST 
    public Response post(String requestBody){ 

     ... 

     //NullPointerException 
     User user = userDAO.loadByCompanyIdAndLogin(companyId, login); 
    } 

    ... 

} 

LoginTest Klasse:

package net.openrally.restaurant.core.exposure.resource; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("/applicationContext.xml") 
public class LoginTest extends BaseResourceTest { 

    @Autowired 
    private UserDAO userDAO; 

    ... 

    @Test 
    public void testInvalidPassword() { 

    .... 

    // Works perfectly! 
    userDAO.save(user); 

    .... 

    } 

} 

applicationContext.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:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 

    <bean id="propertyConfigurer" 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
     <property name="locations"> 
      <list> 
       <value>classpath:configuration.properties</value> 
      </list> 
     </property> 
    </bean> 

    <context:annotation-config /> 
    <context:component-scan base-package="net.openrally.restaurant.core" /> 

    <import resource="db-config.xml" /> 
</beans> 

Ich bin auf der Suche nach einer Lösung seit ein paar Tagen. Von dem, was ich bis jetzt finden konnte, haben die meisten Leute, die @Autowired Probleme haben, entweder <context:annotation-config /> oder xmlns:context="http://www.springframework.org/schema/context" in ihrem Frühling xml oder haben Sie keine @Component Familie Annotation in der Klasse, die DI stattfinden soll, und wie Sie sehen können, sie sind beide da :(. Ich habe nur eine applicationContext.xml in meinem Projekt, die sowohl für die Laufzeit und Test (ich habe unterschiedliche configuration.properties Datenbank Anmeldeinformationen und Protokollebenen unterschiedlich, aber keine Feder-Konfiguration dort)

Ich bin mit:

Spring: 3.1.0.RELEASE 
JUnit: 4.10 
Jersey: 1.11 
CLIB: 2.2.2 

Alle Ideen, und ich meine ANY :), wird sehr geschätzt.

UPDATE

Die folgenden Protokolle kommen, wenn ich den Test ausführen:

2012-03-27 07:37:02,457 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'login' 
2012-03-27 07:37:02,457 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'login' 
2012-03-27 07:37:02,459 DEBUG [main] org.springframework.beans.factory.annotation.InjectionMetadata - Found injected element on class [net.openrally.restaurant.core.exposure.resource.Login]: AutowiredFieldElement for private net.openrally.restaurant.core.persistence.dao.ConfigurationDAO net.openrally.restaurant.core.exposure.resource.Login.configurationDAO 
2012-03-27 07:37:02,459 DEBUG [main] org.springframework.beans.factory.annotation.InjectionMetadata - Found injected element on class [net.openrally.restaurant.core.exposure.resource.Login]: AutowiredFieldElement for private net.openrally.restaurant.core.persistence.dao.UserDAO net.openrally.restaurant.core.exposure.resource.Login.userDAO 
2012-03-27 07:37:02,459 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'login' to allow for resolving potential circular references 
2012-03-27 07:37:02,459 TRACE [main] org.springframework.beans.CachedIntrospectionResults - Getting BeanInfo for class [net.openrally.restaurant.core.exposure.resource.Login] 
2012-03-27 07:37:02,462 TRACE [main] org.springframework.beans.CachedIntrospectionResults - Caching PropertyDescriptors for class [net.openrally.restaurant.core.exposure.resource.Login] 
2012-03-27 07:37:02,462 TRACE [main] org.springframework.beans.CachedIntrospectionResults - Found bean property 'class' of type [java.lang.Class] 
2012-03-27 07:37:02,462 DEBUG [main] org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'login': AutowiredFieldElement for private net.openrally.restaurant.core.persistence.dao.ConfigurationDAO net.openrally.restaurant.core.exposure.resource.Login.configurationDAO 
2012-03-27 07:37:02,462 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'configurationDAO' 
2012-03-27 07:37:02,462 DEBUG [main] org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'login' to bean named 'configurationDAO' 
2012-03-27 07:37:02,463 DEBUG [main] org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'login': AutowiredFieldElement for private net.openrally.restaurant.core.persistence.dao.UserDAO net.openrally.restaurant.core.exposure.resource.Login.userDAO 
2012-03-27 07:37:02,463 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userDAO' 
2012-03-27 07:37:02,463 DEBUG [main] org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'login' to bean named 'userDAO' 
2012-03-27 07:37:02,464 DEBUG [main] org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator - Creating implicit proxy for bean 'login' with 0 common interceptors and 1 specific interceptors 
2012-03-27 07:37:02,464 DEBUG [main] org.springframework.aop.framework.Cglib2AopProxy - Creating CGLIB2 proxy: target source is SingletonTargetSource for target object [[email protected]] 
2012-03-27 07:37:02,465 DEBUG [main] org.springframework.aop.framework.Cglib2AopProxy - Unable to apply any optimisations to advised method: public javax.ws.rs.core.Response net.openrally.restaurant.core.exposure.resource.Login.post(java.lang.String) 

Frühling kann meine Bohne richtig sein zu schaffen, sondern Jersey seine eigene Nicht-autowired Instanz mit?

+0

Gibt es einen Konflikt zwischen '@ Component' und' @ Singleton' auf Ihrer Bean? Und wie wird Ihre 'applicationContext.xml' Datei zur Laufzeit geladen? –

+0

Hallo nico_ekito, danke für deine Eingabe. Das '@ Singleton' ist nur eine Optimierung. Ich habe versucht, es nach Ihrem Kommentar zu entfernen, aber kein Glück ... Die "appliationContext.xml" befindet sich im Ordner Ressourcen und Projekt hat Federabhängigkeiten von Maven gesteuert. Ich plane, Steg als einen Netzbehälter zu verwenden, aber für die Tests verwende ich Grizzly Web Container von Jersey. – robertobado

+0

Aber wie ist Ihre 'applicationContext.xml' Datei in Ihrer Runtime App geladen? Durch einen 'ClassPathXmlApplicationContext'? Durch eine Webapp? –

Antwort

0

Nachdem ich eine Weile geforscht habe, konnte ich keinen Weg finden, GrizzlyWeb den vom Frühling geladenen Kontext zu nutzen, also habe ich versucht, eine alternative Lösung zu finden.

Ich fand dann Hifaces20, die Sie eine Anlegestelle Instanz starten und stoppen lassen, innerhalb des gleichen JVM (was bedeutet, Sie können zum Beispiel eine Memory-Datenbank verwenden, die durch die Tests und die Anwendung sowohl zu sehen sein wird)

0

Ich hatte genau das gleiche Problem und stellte später fest, dass es ein Entwicklerproblem war :)

Ich erstellte ein neues Objekt, anstatt die Frühlingsbohne zu verwenden.

Sagen wir Klasse MyService Autowires eine Dao Klasse MyDao myDaoBean. Jetzt sagen wir, ich möchte MyService in MyController verwenden, sollte ich in der Frühlingsbohne myServiceSpringBean verdrahten. Wenn ich versuche, eine neue myServiceObject zu erstellen, dann verdrahtet Spring die myDaoBean nicht in die myServiceObject, weil es nicht über dieses neue Dienstobjekt bekannt ist.

Und das führt zu myDaoBean wird Null.

Verwandte Themen