2017-08-23 52 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