我在开发中使用SpringTest测试机制进行服务层的单元测试,结果单元测试在执行初始化方法时就抛出异常,错误如下
[code="java"]java.lang.IllegalStateException: Failed to load ApplicationContext
... ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dictionaryManager': Invocation of init method failed; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
... ...
Caused by: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:685)
at com.lily.dap.dao.hibernate.HibernateDao.getSession(HibernateDao.java:73)
at com.lily.dap.dao.hibernate.HibernateDao.createQuery(HibernateDao.java:432)
at com.lily.dap.dao.hibernate.HibernateDao.query(HibernateDao.java:152)
at com.lily.dap.dao.hibernate.HibernateDao.query(HibernateDao.java:113)
at com.lily.dap.service.common.impl.DictionaryManagerImpl.init(DictionaryManagerImpl.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:340)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:293)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:130)
... 39 more[/code]
单元测试类继承了Spring的AbstractTransactionalJUnit4SpringContextTests类,然后测试中使用的Spring配置如下:
applicationContext-dao.xml
[code="java"]<?xml version="1.0" encoding="UTF-8"?>
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
default-lazy-init="true">
Spring DAO 配置文件
<bean id="dao" class="com.lily.dap.dao.hibernate.HibernateDao">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="batchSize" value="20"/>
</bean>
<!-- Hibernate配置 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="namingStrategy">
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.show_sql=${hibernate.show_sql}
hibernate.format_sql=true
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.hbm2ddl.auto=none
</value>
</property>
<property name="packagesToScan" value="com.lily.dap.entity" />
</bean>
<!-- 事务管理器配置,单数据源事务 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
[/code]
DictionaryManagerTest-context.xml
[code="java"]<?xml version="1.0" encoding="UTF-8"?>
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-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">
aop:config
/aop:config
<context:annotation-config/>
<!-- Enable @Transactional support -->
<tx:annotation-driven/>
<!-- Enable @AspectJ support -->
<aop:aspectj-autoproxy/>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true" no-rollback-for="com.lily.dap.service.core.exception.DataNotExistException"/>
<tx:method name="count*" read-only="true" no-rollback-for="com.lily.dap.service.core.exception.DataNotExistException"/>
<tx:method name="*" no-rollback-for="com.lily.dap.service.core.exception.DataNotExistException"/>
</tx:attributes>
</tx:advice>
<bean class="com.lily.dap.service.SpringContextHolder" lazy-init="false"/>
<bean id= "manager" class="com.lily.dap.service.core.ManagerImpl"/>
<bean id= "dictionaryManager" class="com.lily.dap.service.common.impl.DictionaryManagerImpl"/>
[/code]
DictionaryManagerImpl代码大体如下:
[code="java"]@Service("dictionaryManager")
public class DictionaryManagerImpl extends BaseManager implements
DictionaryManager {
/**
* 存放字典使用实体集合的Map,其中key对应那个字典目录,value为这个字典目录有那些实体对象的那个字段使用着
*/
private Map> dictionaryAccessMap = new HashMap>();
@PostConstruct
public void init() {
//读取字典使用实体数据至dictionaryAccessMap,以供在执行删除字典数据时判断数据是否被使用的依据
List<DictAccess> list = dao.query(DictAccess.class, null);
for (DictAccess dictAccess : list) {
String catalogCode = dictAccess.getCatalogCode();
List<DictAccess> dictAccessList = dictionaryAccessMap.get(catalogCode);
if (dictAccessList == null) {
dictAccessList = new ArrayList<DictAccess>();
dictionaryAccessMap.put(catalogCode, dictAccessList);
}
dictAccessList.add(dictAccess);
}
}
... ...
[/code]