2012-03-13 95 views
0

我在單元測試中遇到了@autowired問題。 這裏是相關類和XML文件:Spring數據JPA環境中的JUnit自動裝配問題

服務類:

@Service(value = "statusService") 
public class StatusService implements DefaultService<Status> { 

    @Autowired(required = true) 
    private StatusRepository statusRepository; 

    public void save(Status value) { 
    statusRepository.save(value); 

    } 
} 

接口:

public interface DefaultService<T> { 
    @Transactional 
    void save(T value); 

} 

(我也測試了非通用接口,但結果是一樣的。)

測試類:

@ContextConfiguration(locations={"**/WEB-INF/applicationContext.xml", "**/WEB-INF/hibernate-context.xml"}) 
@RunWith(SpringJUnit4ClassRunner.class) 
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) 
@Transactional 
public class StatusServiceTest 
{ 
    @Autowired 
    private StatusService statusService; 

    @Test 
    public void test() 
    { 
     Status s = new Status(); 
     s.setDescription("desc"); 
     s.setStatus("status"); 

     statusService.save(s); 
    } 
} 

應用程序上下文:

<?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" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"   
    xmlns:jpa="http://www.springframework.org/schema/data/jpa" 

    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 
      http://www.springframework.org/schema/mvc 
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
      http://www.springframework.org/schema/data/jpa 
      http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> 


    <!-- Scans the classpath for annotated components that will be auto-registered as Spring beans. 
    For example @Controller and @Service. Make sure to set the correct base-package--> 
    <context:component-scan base-package="at.jba.ticketbox" /> 
    <jpa:repositories base-package="at.jba.ticketbox.repositories" /> 

    <!-- Activates various annotations to be detected in bean classes --> 
    <context:annotation-config /> 

    <!-- Configures the annotation-driven Spring MVC Controller programming model. 
    Note that, with Spring 3.0, this tag works in Servlet MVC only! --> 
    <mvc:annotation-driven /> 

    <!-- Load Hibernate related configuration --> 
    <import resource="hibernate-context.xml" /> 

</beans> 

Hibernate的-上下文

<?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:tx="http://www.springframework.org/schema/tx" 
     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/tx 
      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
      http://www.springframework.org/schema/context 
      http://www.springframework.org/schema/context/spring-context-3.0.xsd 
      "> 

    <context:property-placeholder location="/WEB-INF/spring.properties" /> 

    <!-- Enable annotation style of managing transactions --> 
    <tx:annotation-driven transaction-manager="transactionManager" /> 

    <!-- Declare the Hibernate SessionFactory for retrieving Hibernate sessions --> 
    <!-- See http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.html -->       
    <!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/SessionFactory.html --> 
    <!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/Session.html --> 
<!-- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" 
       p:dataSource-ref="dataSource" 
       p:configLocation="${hibernate.config}" 
       p:packagesToScan="at.jba.ticketbox"/> --> 

    <!-- Declare a datasource that has pooling capabilities--> 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" 
       p:driverClassName="${jdbc.driver}" 
       p:url="${jdbc.url}" 
       p:username="${jdbc.username}" 
       p:password="${jdbc.password}" 
       /> 


    <!-- Declare a transaction manager--> 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
       p:entityManagerFactory-ref="entityManagerFactory" p:dataSource-ref="dataSource" /> 

     <!-- JPA Entity Manager Factory --> 
    <bean id="entityManagerFactory" 
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
      p:dataSource-ref="dataSource" 
      p:persistenceXmlLocation="META-INF/persistence.xml" 
      p:persistenceUnitName="springJpaPersistenceUnit_TEST" />   


    <!-- bean post-processor for JPA annotations --> 
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

</beans> 

和堆棧跟蹤:

INFO : org.springframework.test.context.TestContextManager - @TestExecutionListeners is not present for class [class at.jba.ticketbox.service.interfaces.DefaultServiceTest]: using defaults. 
INFO : org.springframework.context.support.GenericApplicationContext - Refreshing [email protected]afe611: startup date [Tue Mar 13 15:19:44 CET 2012]; root of context hierarchy 
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring 
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.s[email protected]5543bd5c: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy 
ERROR: org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframewor[email protected]4ad70ab0] to prepare test instance [[email protected]] 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'at.jba.ticketbox.service.interfaces.DefaultServiceTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private at.jba.ticketbox.service.StatusService at.jba.ticketbox.service.interfaces.DefaultServiceTest.sr; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [at.jba.ticketbox.service.StatusService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private at.jba.ticketbox.service.StatusService at.jba.ticketbox.service.interfaces.DefaultServiceTest.sr; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [at.jba.ticketbox.service.StatusService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284) 
    ... 26 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [at.jba.ticketbox.service.StatusService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:924) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:793) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478) 
    ... 28 more 
INFO : org.springframework.context.support.GenericApplicationContext - Closing [email protected]afe611: startup date [Tue Mar 13 15:19:44 CET 2012]; root of context hierarchy 
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.s[email protected]5543bd5c: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy 

我試圖自動裝配,而不是服務類的界面(一般一個太),原因從來就讀,有可能有問題。 我與@Resource試了一下,相同的堆棧跟蹤 我試圖書面方式非通用接口 ...

我覺得奇怪的是,應用程序完美運行的Tomcat服務器作爲Web應用程序上。沒有問題保存和刪除對象。我仍然不明白爲什麼測試不起作用。 plz幫助;)THX

+0

而不是發佈什麼似乎是幾乎所有*** ***你的代碼,請你苗條下來到仍然表現出的問題小例子? – cdeszaq 2012-03-13 14:37:53

+0

這兩個類和一個接口相當小,但好的我會刪除一些方法。但當我不知道他們有什麼問題時,我應該如何修剪xml文件?!我很容易就可以忽略掉重要的細節 – Proton 2012-03-13 15:06:43

回答

2

默認情況下,@ContextConfiguration註釋locations參數假設類路徑:協議,所以你需要明確指定文件:協議在classpath中加載文件時沒有,例如上下文位於WEB-INF文件夾中:

@ContextConfiguration(locations={ 
    "file:**/WEB-INF/applicationContext.xml", "file:**/WEB-INF/hibernate-context.xml"}) 
@RunWith(SpringJUnit4ClassRunner.class) 
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) 
@Transactional 
public class StatusServiceTest 
    ... 
+0

如此接近,刪除了我在WEB-INF被隱藏的答案。 – dardo 2012-03-13 15:33:19

+0

thx的建議。但同時我只在src/test/recources文件夾中設置了一個新的配置設置,只在meta-inf文件夾中包含一個applicationContext.xml和一個persistence.xml。這是dardo在你的答案之前提出的;)問題仍然存在。 – Proton 2012-03-13 16:25:57

+0

但我在「舊」版本中嘗試了「file:」的建議。同樣的錯誤... :( – Proton 2012-03-13 16:27:57