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/











0 0
原创粉丝点击