unitils 测试框架介绍(一)
来源:互联网 发布:sai for mac下载 编辑:程序博客网 时间:2024/04/24 03:39
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>@Testpublic 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>@Testpublic void testArrayLenientEquals(){ Integer orderList1[] = new Integer[]{1,2,3}; Integer orderList2[] = new Integer[]{3,2,1}; assertLenientEquals(orderList1, orderList2);}3、assertPropertyXxxEquals: 属性断言
@Testpublic 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 {@SpringApplicationContextpublic ApplicationContext applicationContext;@Testpublic void testApplicationContext(){assertNotNull(applicationContext);}}
public class SimpleUserServiceTest extends BaseServiceTest {//通过ID 注入Bean@SpringBean("userService")private UserService userService1;//通过类型注入Bean@SpringBeanByTypeprivate UserService userService2; // 通过name 注入Bean@SpringBeanByNameprivate UserService userService;@Testpublic void testApplicationContext(){assertNotNull(applicationContext);}@Testpublic 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") @HibernateSessionFactorypublic SessionFactory sessionFactory;@Testpublic 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的datasouceIdString 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.MultiSchemaXlsDataSetFactoryDbUnitModule.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.OracleDriverdatabase.url=jdbc:oracle:thin:@172.16.5.242:1521:orcldatabase.dialect = org.hibernate.dialect.HSQLDialectdatabase.userName=unitilsdatabase.schemaNames=UNITILS# The database maintainer is disabled by default.#数据库维护策略 在每次运行时可更新数据库 根据dbMaintainer.script.locations设置的sql文件进行更新#当以往文件改变 将更新此文件到数据库 未改变的sql文件将不变#命名格式 <index>_<some name>.sqlupdateDataBaseSchema.enabled=true#This table is by default not created automatically#数据库表生成策略dbMaintainer.autoCreateExecutedScriptsTable=truedbMaintainer.keepRetryingAfterError.enabled=truedbMaintainer.script.locations=E:/data/Spring3.X/chapter16/resources/dbscripts#配置数据集工厂DbUnitModule.DataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactoryDbUnitModule.ExpectedDataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory#配置数据库加载策略DbUnitModule.DataSet.loadStrategy.default=org.unitils.dbunit.datasetloadstrategy.impl.CleanInsertLoadStrategyDatabaseModule.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.SpringModuleunitils.module.spring.runAfter=databaseunitils.module.spring.enabled=truedatabase.userName=unitilsdatabase.password=unitilsdatabase.schemaNames=UNITILS#shcemaNames 必须为大写#增加如下配置org.unitils.core.dbsupport.DbSupport.implClassName=org.unitils.core.dbsupport.OracleDbSupportorg.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/
- unitils 测试框架介绍(一)
- unitils 测试框架介绍(二)
- UNITILS 测试框架
- Unitils介绍(一)
- unitils学习2一使用Unitils测试DAO层
- unitils学习3一使用unitils测试Service层
- 单元测试之测试整合框架Unitils
- Unitils配置文件(Unitils介绍四)
- Lenient assertions(Unitils介绍三)
- Maven整合Junit unitils测试框架 cannot retrieve JUnit method
- 16.2 测试之unitils
- unitils学习1一Unitils基础简介
- 测试整合之王Unitils(单元测试系列)
- Unitils介绍(二)-- Assertion utilities
- Acegi框架介绍(一)
- openlayers框架介绍(一)
- thinkPHP框架介绍(一)
- Spring框架介绍(一)
- StringBuffer和StringBuilder的区别
- 使用thrift做c++,java和python的相互调用
- Android中JNI编程详解
- 排序算法,选择,插入,冒泡,希尔,归并
- 包装类DataOutputStream、DataInputStream的常见用法
- unitils 测试框架介绍(一)
- 这才是真正意义上的“扶手”
- 栈
- 大臣的旅费
- C/C++与Lua的相互调用
- J2EE事务并发控制策略总结
- MFC学习之 自定义资源文件
- 【足迹C++ primer】9.try语句块和异常处理
- 链表