基于Spring的测试类进行DAO层集成测试实践(1)

资源准备:

mysql5.0

spring-2.5

hibernate-3.2.5

junit-4.4.jar

 

 

 

 

创建表

 

DROP TABLE IF EXISTS `myproject`.`boys`;
CREATE TABLE  `myproject`.`boys` (
  `id` bigint(20) NOT NULL auto_increment,
  `phone` varchar(20) default NULL,
  `sex` varchar(2) default NULL,
  `address` varchar(255) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

创建相关配置文件:

 

(1)applicationContext-resources.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:p="http://www.springframework.org/schema/p"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jee="http://www.springframework.org/schema/jee"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
   http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
 
 
 <!--<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
  <list>
  <value>classpath:jdbc.properties</value>
  </list>
  </property>
  </bean>
 -->
 <context:property-placeholder location="classpath:jdbc.properties" />
 <!-- =====使用dbcp 连接池 -->
 <bean id="dataSource"
  class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
  p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}"
  p:username="${jdbc.username}" p:password="${jdbc.password}" />
 <!-- Hibernate SessionFactory -->
 <bean id="sessionFactory"
  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
  p:dataSource-ref="dataSource"
  p:mappingResources="testHibernate.hbm.xml">
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">
     ${hibernate.dialect}
    </prop>
    <prop key="hibernate.show_sql">
     ${hibernate.show_sql}
    </prop>
    <!--<prop key="hibernate.generate_statistics">
     ${hibernate.generate_statistics}
     </prop>
    -->
   </props>
  </property>
 </bean>
 <bean id="transactionManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager"
  p:sessionFactory-ref="sessionFactory" />
 <tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
   <tx:method name="find*" read-only="true" />
   <tx:method name="get*" read-only="true" />
   <!-- 所有抛出异常都要回滚 -->
   <tx:method name="*" rollback-for="Throwable" />
  </tx:attributes>
 </tx:advice>

<!-- com.jmesa.test.service包下面(包括子包)后缀为Service的所有bean -->
 <aop:config>
  <aop:pointcut id="serviceOperation"
   expression="execution(* com.jmesa.test.service..*Service.*(..))" />
  <aop:advisor pointcut-ref="serviceOperation"
   advice-ref="txAdvice"/>
 </aop:config>
</beans>

 

(2) applicationContext-dao.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:p="http://www.springframework.org/schema/p"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jee="http://www.springframework.org/schema/jee"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
   http://www.springframework.org/schema/jee htp://www.springframework.org/schema/jee/spring-jee-2.5.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
 
 
 <bean name="boysDAO" class="com.jmesa.test.dao.hibernate.BoysDAOImpl" autowire="byName"></bean>
</beans>

 

(3)jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/myproject?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true

(4) boys 实体的hibernate配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping auto-import="true" default-lazy="false">
 <class name="com.jmesa.test.model.Boy" table="boys">
  <id name="id" column="id" type="long">
   <generator class="identity"></generator>
  </id>
  <property name="phone" column="phone"></property>
  <property name="sex" column="sex"></property>
  <property name="address"></property>
 </class>
</hibernate-mapping>

 

 

创建BoysDAO 接口

 

package com.jmesa.test.dao;

import java.util.List;

import com.jmesa.test.common.EntityFilters;
import com.jmesa.test.common.EntitySorts;
import com.jmesa.test.model.Boy;

public interface BoysDAO {
 /**
  *
  * @param boy
  *            域对象
  */
 public void save(Boy boy);

 /**
  * 更新boy数据
  *
  * @param boy
  */
 public void update(Boy boy);

 /**
  * 依据id值获得boy域对象
  *
  * @param id
  * @return
  */
 public Boy get(String id);

 /**
  * 获得所有boy域对象
  *
  * @return
  */
 public List<Boy> getAll();

/**
  * 依据boy 属性条件查询boy列表
  *
  * @param phone
  *            空或者null值将不作为查询条件
  * @param sex
  *            空或者null值将不作为查询条件
  * @return
  */
 public List<Boy> queryBoys(String phone, String sex);

}

 

BoysDAO 接口实现类:

package com.jmesa.test.dao.hibernate;

import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.jmesa.test.dao.BoysDAO;
import com.jmesa.test.model.Boy;

public class BoysDAOImpl extends HibernateDaoSupport implements BoysDAO {

 public Boy get(String id) {
  return (Boy) this.getHibernateTemplate().load(Boy.class, id);
 }

 public List<Boy> getAll() {
  return queryBoys(null, null);
 }

 public List<Boy> queryBoys(String phone, String sex) {
  DetachedCriteria query = DetachedCriteria.forClass(Boy.class);
  if (phone != null && !phone.equals("")) {
   query.add(Property.forName("phone").eq(phone));
  }
  if (sex != null && !sex.equals("")) {
   query.add(Property.forName("sex").eq(sex));
  }
  return this.getHibernateTemplate().findByCriteria(query);
 }

public void save(Boy boy) {
  this.getHibernateTemplate().save(boy);

 }

public void update(Boy boy) {
  this.getHibernateTemplate().update(boy);
 }

}

 

开始测试:

基于AbstractTransactionalDataSourceSpringContextTests 创建测试基类:

package com.jmesa.test.integrateTest;

import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;

public class BaseDataSourceSpringContextIntegrationTest extends
  AbstractTransactionalDataSourceSpringContextTests {

//加载spring配置文件,其路径在classpath的根目录下
 private static final String[] configFiles = new String[] {
   "applicationContext-resources.xml", "applicationContext-dao.xml" };

//设置dao类的注入方式,默认为类型注入,此处改为名称注入

public BaseDataSourceSpringContextIntegrationTest() {
  this.setAutowireMode(AUTOWIRE_BY_NAME);
 }

//通过此方法提供spring配置文件

protected String[] getConfigLocations() {
  return configFiles;
 }
}

 

BoysDAO的测试类:

 

package com.jmesa.test.integrateTest;

import java.util.List;

import org.junit.Assert;
import org.junit.Test;

import com.jmesa.test.common.EntityFilters;
import com.jmesa.test.common.EntitySorts;
import com.jmesa.test.dao.BoysDAO;
import com.jmesa.test.model.Boy;

/**
 * @author   jack
 */
public class BoyDAOTest extends BaseDataSourceSpringContextIntegrationTest {
 private BoysDAO boysDAO;

public BoyDAOTest(){
 }
 /**
  * 必须要提供变量boysDAO的setter方法,这样注入才会成功
  */
 public void setBoysDAO(BoysDAO boysDAO) {
  this.boysDAO = boysDAO;
 }

@before

 public void initialize(){

 }

@after

public void destroy(){

}

@Test
 public void testGetAll(){
  int count = this.countRowsInTable("boys");
  Assert.assertEquals(boysDAO.getAll().size(),count);
 }
 @Test
 public void testQueryBoys(){
  Assert.assertEquals(0,boysDAO.queryBoys("www", "wwww").size());
  Assert.assertEquals(1,boysDAO.queryBoys("eee", "33").size());
 }
 @Test
 public void testSave(){
  int boysCount = this.countRowsInTable("boys");
  String phone ="13401108995";
  String sex = "1";
  String address = "南京路";
  Boy boy = new Boy();
  boy.setPhone(phone);
  boy.setSex(sex);
  boy.setAddress(address);
  boysDAO.save(boy);
  Assert.assertEquals(boysCount+1, this.countRowsInTable("boys")); 
 }
 @Test
 public void testGetBoysCountWithFilter(){
  EntityFilters entityFilters = new EntityFilters();
  int count = boysDAO.getBoysCountWithFilter(entityFilters);
  Assert.assertEquals(20, count);
  EntityFilters entityFilters1 = new EntityFilters();
  entityFilters1.addFilter("phone", "342432");
  int size = entityFilters1.filterSize();
  int count1 = boysDAO.getBoysCountWithFilter(entityFilters1);
  Assert.assertEquals(1, count1);
 }
 @Test
 public void testGetBoysWithFilterAndSort(){
  EntityFilters entityFilters = new EntityFilters();
  //entityFilters.addFilter("phone", "342432");
  EntitySorts entitySorts = new EntitySorts();
  entitySorts.addSort("phone", "desc");
  List<Boy> boysList = boysDAO.getBoysWithFilterAndSort(entityFilters, entitySorts, 0, 10);
  Assert.assertEquals(10, boysList.size());
  Boy boy = boysList.get(0);
  Assert.assertEquals("ww",boy.getPhone() );
  
 }

 

 

 

 

 

此处测试用到了 AbstractTransactionalDataSourceSpringContextTests 的四方面的功能:

1. 加载spring的资源配置文件

2. dao bean 引入测试类

3. 简便的函数使用,如:countRowsInTable

4. 事务自动回滚.

 

请注意此BoyDAOTest测试类中使用@before,@after修饰的方法在测试中没有被执行, 可能原因是BoyDAOTest 间接继承了TestCase类,要想执行此类方法,必须沿用以前版本的junit的setUp,tearDown

方法,然而AbstractTransactionalDataSourceSpringContextTests 类已经overide此方法,并且加了final修饰,其子类不可以在overide了. 所以加入类似before,after这样的方法,目前还没有想出比较好的办法? 还请大侠们赐教.

 

 

 

参考文献:http://www.infoq.com/articles/testing-in-spring

 

 

 

 

 

 

 

 

你可能感兴趣的:(DAO,spring,AOP,Hibernate,jdbc)