unitils 测试框架介绍(一)

  Junit 是用于自动化测试Java代码的框架,而Unitils是测试整合之王,目的是 让单元测试更加容易和可维护,Unitils构建在DbUnit与EasyMock 项目之上并与JUnit和TestNG相结合,支持数据库测试,支持利用Mock对象进行测试并提供与Spring和Hibernate相集成。Unitils模块组件有一下组成:

1、unitils-core: 核心内核包

2、unitils-database: 维护测试数据库及连接池

3、unitils-DbUnit: 使用Dbunit管理测试数据

4、unitils-easymock:支持创建Mock 和宽松的反射参数匹配

5、unitils-inject: 支持一个对象注入另一个对象

6、unitils-mock:整合各种Mock,在Mock 的使用语法上进行简化。

7、unitils-orm:支持Hibernate、JPA 的配置和自动数据库映射检查

8、unitils-spring:支持加载spring 的上下文配置,并检索和Spring Bean 注入。

Unitils 配置文件:

1、unitils-default.properites; 默认配置属性
2、unitils.properties:项目级配置属性

3、unitils-local.properties:特定用户的配置属性

Unitils断言:
1、assertReflectionEquals: 反射断言

<span style="white-space:pre">	</span>@Test
	public void testReflectionEquals(){
		User user1 = new User("tom","1234");
		User user2 = new User("tom","1234");
	       assertReflectionEquals(user1, user2);//循环比较对象属性值是否相等
	}

2、assertLenientEquals:  忽略顺序和时间设置的断言

<span style="white-space:pre">	</span>@Test
	public void testArrayLenientEquals(){
	    Integer orderList1[] = new Integer[]{1,2,3};
	    Integer orderList2[] = new Integer[]{3,2,1};
	    assertLenientEquals(orderList1, orderList2);
}
3、assertPropertyXxxEquals: 属性断言

	@Test
	public void testPropertyLenientEquals(){
		User user = new User("tom","1234");
		assertPropertyReflectionEquals("userName", "tom", user);
		assertPropertyLenientEquals("lastVisit", null, user);
	}
集成Spring:

支持一下特性:

1、ApplicationContext 配置管理

2、在单元测试代码中注入Spring的Beans;

3、使用定义在Spring配置文件中的Hibernate SessionFacotry

4、引用在Spring配置中的Unitils 数据源

@SpringApplicationContext({"baobaotao-service.xml", "baobaotao-dao.xml"})
public class BaseServiceTest extends UnitilsJUnit4 {
	@SpringApplicationContext
	public ApplicationContext applicationContext;
	@Test
	public void testApplicationContext(){
		assertNotNull(applicationContext);
	}
}
public class SimpleUserServiceTest extends BaseServiceTest {
	
	//通过ID 注入Bean
	@SpringBean("userService")
	private UserService userService1;
	//通过类型注入Bean
	@SpringBeanByType
	private UserService userService2;
        // 通过name 注入Bean
	@SpringBeanByName
	private  UserService userService;

	@Test
	public void testApplicationContext(){
		assertNotNull(applicationContext);
	}

	@Test
	public void testUserService(){
		assertNotNull(userService);
		assertNotNull(userService1);
		assertNotNull(userService2);
		assertEquals("john123",userService.findUserByUserName("john123").getUserName());
		assertEquals("john123",userService1.findUserByUserName("john123").getUserName());
		assertEquals("john123",userService2.findUserByUserName("john123").getUserName());
	}


}

通过@SpringApplicationContext 注解,首先扫描父类中的配置文件,如果找到了,就先加载父类的配置文件,然后加载子类重写的配置文件盒特定的配置文件,而且在父类中配置spring 配置文件,可以防治让子类的测试方法重复加载配置文件,这样spring应用上下文只会创建一次。

Hibernate 集成:

@HibernateSessionFactory("hibernate.cfg.xml")
//@SpringApplicationContext({"baobaotao-service.xml", "baobaotao-dao.xml"})
public class BaseDaoTest extends UnitilsJUnit4 {
//	@SpringBean("sessionFactory")
      @HibernateSessionFactory
	public SessionFactory sessionFactory;
	
	@Test
	public void testSessionFactory(){
		assertNotNull(sessionFactory);
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<!-- SQL方言,这边设定的是HSQL -->
		<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
		<!-- 数据源的名称 -->
		<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
		<property name="hibernate.connection.url">jdbc:oralce:thin:@172.16.129.139:1521/qcjkdb</property>
		<!--设置连接数据库的用户名-->
		<property name="hibernate.connection.username">jtkfpt</property>
		<!--设置连接数据库的密码-->
		<property name="hibernate.connection.password">jtkfpt</property>
		<!--设置显示sql语句方便调试-->
		<property name="hibernate.show_sql">true</property>
		<!-- 配置映射 -->
		<property name="configurationClass">org.hibernate.cfg.AnnotationConfiguration</property>
		<mapping class="com.baobaotao.domain.User" />
		<mapping class="com.baobaotao.domain.LoginLog" />
	 </session-factory>
</hibernate-configuration>

最好将@HibernateSessionFactory 放入到父类中,防止子类重复加载配置文件。

集成DbUnit:

DAO层测试

利用DbUnit 模块可以从Excel、XML中读取数据写入数据库,简化数据库测试工作。下面以读取Excel数据为例:

public class MultiSchemaXlsDataSetFactory implements DataSetFactory {

	protected String defaultSchemaName;

	//初始化
	public void init(Properties configuration, String defaultSchemaName) {
		this.defaultSchemaName = defaultSchemaName;
	}

	//创建数据集
	public MultiSchemaDataSet createDataSet(File... dataSetFiles) {
		try {
			MultiSchemaXlsDataSetReader xlsDataSetReader = new MultiSchemaXlsDataSetReader(
					defaultSchemaName);
			return xlsDataSetReader.readDataSetXls(dataSetFiles);
		} catch (Exception e) {
			throw new UnitilsException("创建数据集失败: "
					+ Arrays.toString(dataSetFiles), e);
		}
	}

	// 获取数据集文件的扩展名
	public String getDataSetFileExtension() {
		return "xls";
	}

}
//EXCEL数据集读取器
public class MultiSchemaXlsDataSetReader {
	private String defaultSchemaName;
	
	public MultiSchemaXlsDataSetReader(String defaultSchemaName) {
		this.defaultSchemaName = defaultSchemaName;
	}	

	public MultiSchemaDataSet readDataSetXls(File... dataSetFiles) {
		try {
			Map<String, List<ITable>> tableMap = getTables(dataSetFiles);
			MultiSchemaDataSet dataSets = new MultiSchemaDataSet();
			for (Entry<String, List<ITable>> entry : tableMap.entrySet()) {
				List<ITable> tables = entry.getValue();
				try {
					DefaultDataSet ds = new DefaultDataSet(tables
							.toArray(new ITable[] {}));
					dataSets.setDataSetForSchema(entry.getKey(), ds);
				} catch (AmbiguousTableNameException e) {
					throw new UnitilsException("构造DataSet失败!",  e);
				}
			}
			return dataSets;
		} catch (Exception e) {
			throw new UnitilsException("解析EXCEL文件出错:", e);
		}
	}

	private Map<String, List<ITable>> getTables(File... dataSetFiles) {
		Pattern pattern = Pattern.compile("\\.");
		Map<String, List<ITable>> tableMap = new HashMap<String, List<ITable>>();
		// 需要根据schema把Table重新组合一下
		try {
			for (File file : dataSetFiles) {
				IDataSet dataSet = new XlsDataSet(new FileInputStream(file));
				String[] tableNames = dataSet.getTableNames();
				for (String each : tableNames) {
					// 这个实际上不是schema, 是对应的spring的datasouceId
					String schema = null;
					String tableName;
					String[] temp = pattern.split(each);
					if (temp.length == 2) {
						schema = temp[0];
						tableName = temp[1];
					} else {
						schema = this.defaultSchemaName;
						tableName = each;
					}
					ITable table = dataSet.getTable(each);
					if (!tableMap.containsKey(schema)) {
						tableMap.put(schema, new ArrayList<ITable>());
					}
					tableMap.get(schema).add(new XlsTable(tableName, table));
				}
			}
		} catch (Exception e) {
			throw new UnitilsException("创建数据集失败: "
					+ Arrays.toString(dataSetFiles), e);
		}
		return tableMap;
	}
	//构造XslTable表
	class XlsTable extends AbstractTable {
		private ITable delegate;
		private String tableName;

		public XlsTable(String tableName, ITable table) {
			this.delegate = table;
			this.tableName = tableName;
		}

		public int getRowCount() {
			return delegate.getRowCount();
		}

		public ITableMetaData getTableMetaData() {
			ITableMetaData meta = delegate.getTableMetaData();
			try {
				return new DefaultTableMetaData(tableName, meta.getColumns(),
						meta.getPrimaryKeys());
			} catch (DataSetException e) {
				throw new UnitilsException("Don't get the meta info from  "
						+ meta, e);
			}
		}

		public Object getValue(int row, String column) throws DataSetException {
			Object delta = delegate.getValue(row, column);
			if (delta instanceof String) {
				if (StringUtils.isEmpty((String) delta)) {
					return null;
				}
			}
			return delta;
		}

	}
}

以上是读取Excel数据的两个类,根据传入多个Excel文件,构造一个多数据集,一个数据集对应一个文件,其中一个sheet页代表一个table,最后将返回MultiSchemaDataSet类型对象,这样通过@DataSet注解,将自动解析Excel数据。

想利用上述数据集工厂类,需要在unitils.properties中配置数据集工厂类:

#配置数据集工厂
DbUnitModule.DataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory
DbUnitModule.ExpectedDataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory

此外还要配置unitils 测试环境。

unitils.properties

#启用的unitils 模块
unitils.modules=database,dbunit,hibernate,spring,
#配置扩展模块
#unitils.module.dbunit.className=sample.unitils.module.CustomExtModule

#database
#database.driverClassName=org.hsqldb.jdbcDriver
#database.url=jdbc:hsqldb:data/sampledb16;shutdown=true
#database.dialect = hsqldb
#database.userName=sa
#配置数据库连接
database.driverClassName=oracle.jdbc.driver.OracleDriver
database.url=jdbc:oracle:thin:@172.16.5.242:1521:orcl
database.dialect = org.hibernate.dialect.HSQLDialect
database.userName=unitils
database.schemaNames=UNITILS



# The database maintainer is disabled by default.
#数据库维护策略  在每次运行时可更新数据库 根据dbMaintainer.script.locations设置的sql文件进行更新
#当以往文件改变 将更新此文件到数据库  未改变的sql文件将不变
#命名格式   <index>_<some name>.sql
updateDataBaseSchema.enabled=true
#This table is by default not created automatically
#数据库表生成策略
dbMaintainer.autoCreateExecutedScriptsTable=true
dbMaintainer.keepRetryingAfterError.enabled=true
dbMaintainer.script.locations=E:/data/Spring3.X/chapter16/resources/dbscripts

#配置数据集工厂
DbUnitModule.DataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory
DbUnitModule.ExpectedDataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory

#配置数据库加载策略
DbUnitModule.DataSet.loadStrategy.default=org.unitils.dbunit.datasetloadstrategy.impl.CleanInsertLoadStrategy
DatabaseModule.Transactional.value.default=commit



# XSD generator
#配置数据集结构模式XSD生成路径
dataSetStructureGenerator.xsd.dirName=resources/xsd

数据库加载策略包括以下:

CleanInsertLoadStrategy: 每次先删除数据,再插入数据。

InsertLoadStrategy: 只插入数据。

RefreshLoadStrategy: 有同样key的数据更新,其他插入。

UpdateLoadStrategy: 有同样key的数据更新,其他不插入。


unitils-local.properties:

####################################
# Default configuration of Unitils #
####################################
unitils.module.spring.className=org.unitils.spring.SpringModule
unitils.module.spring.runAfter=database
unitils.module.spring.enabled=true

database.userName=unitils
database.password=unitils
database.schemaNames=UNITILS
#shcemaNames 必须为大写

#增加如下配置

org.unitils.core.dbsupport.DbSupport.implClassName=org.unitils.core.dbsupport.OracleDbSupport
org.dbunit.dataset.datatype.IDataTypeFactory.implClassName=org.dbunit.dataset.datatype.DefaultDataTypeFactory

测试数据库:

 首先在数据库中建表,可以利用unitils.properties数据库表生成策略,指定sql文件来创建数据表。但其有严格的命名规则  <index>_<name>.sql

create table t_user (user_id number(38) not null,user_name varchar2(30),credits number(38),password  varchar2(32),last_visit date,last_ip  varchar2(23), primary key (user_id));
CREATE TABLE t_login_log (login_log_id number(38) not null, user_id   number(38),ip  VARCHAR2(23),login_datetime date,primary key (login_log_id));

用Excel准备测试数据:


测试类:

	@Test
	@DataSet("BaobaoTao.Users.xls")//?????? 
	public void findUserByUserName() {
		User user = userDao.findUserByUserName("tony");
		user = userDao.findUserByUserName("jan");
		assertEquals("jan", user.getUserName());
		assertEquals("123456",user.getPassword());
		assertEquals(new Long(10),user.getCredits());
	}
简单的测试方法,通过@DataSet注解,unitils将利用 MultiSchemaXlsDataSetFactory解析数据,并利用数据加载策略,将Excel数据插入到数据库表中,先简单介绍,下节将重点介绍Service层、Web层测试,以上都是unitils 测试的基本介绍以及测试准备工作。

unitils: http://www.unitils.org/











  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值