2017-08-23 81 views
0

我將ehcache添加到我的項目中,並且我的DAO的單元測試類運行良好,如果我評論ehcache註釋我的DAO和失敗,如果我取消註釋他們,說它不能自動裝載DAO豆。將ehcache添加到DAO類後,Junit測試失敗,無法在測試類中實例化DAO

這是錯誤我得到:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.nicobrest.kamehouse.dao.DragonBallUserDaoJpaTest': Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.nicobrest.kamehouse.dao.DragonBallUserDaoJpa com.nicobrest.kamehouse.dao.DragonBallUserDaoJpaTest.dragonBallUserDaoJpa; 
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.nicobrest.kamehouse.dao.DragonBallUserDaoJpa] 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), @org.springframework.beans.factory.annotation.Qualifier(value=dragonBallUserDaoJpa)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) 
    at 
... 

我也嘗試過的,而不是在單元測試中採用自動裝配的DAO豆,自動裝配應用程序上下文和名稱獲取豆,當我做到這一點,我得到一個異常,它不能將$ proxy32投射到我的DAO類。

java.lang.ClassCastException: com.sun.proxy.$Proxy32 cannot be cast to com.nicobrest.kamehouse.dao.DragonBallUserDaoJpa 
    at com.nicobrest.kamehouse.dao.DragonBallUserDaoJpaTest.setUp(DragonBallUserDaoJpaTest.java:71) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) 
    at 
... 

這些都是相關的文件:

的applicationContext.xml

... 
<cache:annotation-driven cache-manager="cacheManager"/> 
<import resource="applicationContext-persistence.xml" /> 

<!-- Ehcache configuration --> 
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> 
    <property name="cacheManager" ref="ehcache" /> 
</bean> 

<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> 
    <property name="configLocation" value="classpath:ehcache.xml" /> 
    <property name="shared" value="true" /> 
</bean> 

<!-- Example endpoints beans --> 
<bean id="dragonBallUserService" class="com.nicobrest.kamehouse.service.DragonBallUserService"> 
    <property name="dragonBallUserDao" ref="dragonBallUserDaoJpa" /> 
</bean> 

<bean id="dragonBallUserDaoJpa" class="com.nicobrest.kamehouse.dao.DragonBallUserDaoJpa"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 
... 

DragonBallUserDaoJpaTest.java

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) 
public class DragonBallUserDaoJpaTest { 

private static final Logger LOGGER 
LoggerFactory.getLogger(DragonBallUserDaoJpaTest.class); 

@Autowired 
@Qualifier("dragonBallUserDaoJpa") 
private DragonBallUserDaoJpa dragonBallUserDaoJpa; 
... 
@Test 
public void createDragonBallUserTest() { 

    DragonBallUser dragonBallUser = new DragonBallUser(null, "vegeta", "[email protected]", 49, 40, 
     1000); 

    try { 
    assertEquals(0, dragonBallUserDaoJpa.getAllDragonBallUsers().size()); 
    dragonBallUserDaoJpa.createDragonBallUser(dragonBallUser); 
    assertEquals(1, dragonBallUserDaoJpa.getAllDragonBallUsers().size()); 
    dragonBallUserDaoJpa 
     .deleteDragonBallUser(dragonBallUserDaoJpa.getDragonBallUser("vegeta").getId()); 
    } catch (KameHouseBadRequestException | KameHouseNotFoundException e) { 
    e.printStackTrace(); 
    fail("Caught unexpected exception."); 
    } 
} 
... 

DragonBallUserDaoJpa.java

public class DragonBallUserDaoJpa implements DragonBallUserDao { 

@Autowired 
private EntityManagerFactory entityManagerFactory; 
... 
@CacheEvict(value = { "getAllDragonBallUsersCache" }, allEntries = true) 
public Long createDragonBallUser(DragonBallUser dragonBallUser) { 

    EntityManager em = getEntityManager(); 
    try { 
    em.getTransaction().begin(); 
    em.persist(dragonBallUser); 
    em.getTransaction().commit(); 
    } catch (PersistenceException pe) { 
    ... 
    } finally { 
    em.close(); 
    } 
    return dragonBallUser.getId(); 
} 
... 

我不知道還有什麼嘗試,有什麼想法?我使用Spring 4.2.4.RELEASE,Hibernate 5.1.0.Final,Hibernate JPA 1.0.0.Final,ehcache 2.9.0,JUnit 4.12。

這絕對是與ehcache相關的東西,因爲註釋註釋使測試類中的DAO自動裝載成爲可能,單元測試通過了,但我嘗試了幾個小時並且無法弄清楚。

謝謝!

+0

如果變量名稱相同,或者類路徑中只有一個可用的bean,則可以開始移除不需要的限定符。嘗試在bean的聲明中使用名稱。限定符使用名稱而不是id –

+0

我一開始沒有建議它,但我會建議使用class config而不是xml config。在運行前查找錯誤更容易 –

+0

感謝您的答案!我試圖刪除限定符,但它沒有奏效。自動裝配到接口而不是類解決了問題。我實際上計劃將所有內容都移動到類配置中,我想要練習class和xml配置。 – nbrest

回答

2

的第一個錯誤是因爲你試圖注入到DragonBallUserDaoJpa,而不是DragonBallUserDao 。爲了能夠添加緩存層,Spring爲你的類創建了一個代理。這個代理實現了類的接口(DragonBallUserDao),然後委託給實際的類(DragonBallUserDaoJpa)。

您在檢索bean時有同樣的問題。由於代理僅實現接口,因此不能將其轉換爲實現。所以ClassCastException

所以,如果你這樣做在您的測試(你不需要在預選賽)

@Autowired 
private DragonBallUserDao dragonBallUserDao; 

它應該做的伎倆。

另一個解決方案(但我不認爲它很有用)是強制Spring使用cglib創建代理。這樣,你的代理人的確會擴展到具體的類。你需要像這樣的東西:<aop:aspectj-autoproxy proxy-target-class="true" />

最後,你也可以擺脫接口,因爲我非常懷疑你有這個DAO的很多實現。所以界面沒用,只是增加了噪音。刪除它將迫使Spring創建一個cglib代理,因爲沒有接口可用。

+0

太棒了!感謝你的回答!按照您的建議自動裝配到界面而不是類。 @Autowired私人DragonBallUserDao dragonBallUserDaoJpa;我必須使用變量名和後綴Jpa,因爲我有另一個接口的實現。我絕對同意,只有一個實現有一個接口會增加噪音而不是價值,但我實際上有2個實現,我將添加另一個沒有SQL的數據庫。我正在使用這個項目來繼續學習。我絕對需要更多地瞭解方面和proxys。謝謝您的幫助! – nbrest

0

你的junit不會加載你的spring conf xml。

試試這個:

@ContextConfiguration(locations = { 
    "classpath:pathTo/applicationContext.xml"}) 

編輯:嘗試刪除預選賽和/或添加的name屬性在bean創建

+0

對不起,我應該發佈我的完整課程。它實際上會加載它。我有這個註釋。它在將ehcache註釋添加到它之前工作並加載了DAO。我更新了更多相關信息的課程 – nbrest