Unitils测试框架目的是让单元测试变得更加容易和可维护。Unitils构建在DbUnit与EasyMock项目之上并与JUnit和TestNG相结合。支持数据库测试,支持利用Mock对象进行测试并提供与Spring和Hibernate相集成。Unitils设计成以一种高度可配置和松散耦合的方式来添加这些服务到单元测试中,目前其最新版本是3.1。
Unitils功能特点
自动维护和强制关闭单元测试数据库(支持Oracle、Hsqldb、MySQL、DB2)。
简化单元测试数据库连接的设置。
简化利用DbUnit测试数据的插入。
简化Hibernate session管理。
自动测试与数据库相映射的Hibernate映射对象。
易于把Spring管理的Bean注入到单元测试中,支持在单元测试中使用Spring容器中的Hibernate SessionFactory。
简化EasyMock Mock对象创建。
简化Mock对象注入,利用反射等式匹配EasyMock参数。
Unitils模块组件
Unitils通过模块化的方式来组织各个功能模块,采用类似于Spring的模块划分方式,如unitils-core、unitils-database、unitils-mock等。比以前整合在一个工程里面显得更加清晰,目前所有模块如下所示:
unitils-core:核心内核包。
unitils-database:维护测试数据库及连接池。
unitils-DbUnit:使用DbUnit来管理测试数据。
unitils-easymock:支持创建Mock和宽松的反射参数匹配。
unitils-inject:支持在一个对象中注入另一个对象。
unitils-mock:整合各种Mock,在Mock的使用语法上进行了简化。
unitils-orm:支持Hibernate、JPA的配置和自动数据库映射检查。
unitils-spring:支持加载Spring的上下文配置,并检索和Spring Bean注入。
Unitils的核心架构中包含Moudule和TestListener两个概念,类似Spring中黏连其他开源软件中的FactoryBean概念。可以看成第三方测试工具的一个黏合剂。
通过TestListener可以在测试运行的不同阶段注入某些功能。同时某一个TestListener又被一个对应的Module所持有。Unitils也可以看成一个插件体系结构,TestListener在整个Unitils中又充当了插件中扩展点的角色,从TestListener这个接口中我们可以看到,它可以在crateTestObject、before(after)Class、before(after)TestMethod、beforeSetup、afterTeardown的不同切入点添加不同的动作。
Unitils配置文件
unitils-defaults.properties:默认配置文件,开启所有功能。
unitils.properties:项目级配置文件,用于项目通用属性配置。
unitils-local.properties:用户级配置文件,用于个人特殊属性配置。
Unitils的配置定义了一般配置文件的名字unitils.properties和用户自定义配置文件unitils-local.properties,并给出了默认的模块及模块对应的className,便于Unitils加载对应的模块module。但是如果用户分别在unitils.properties文件及unitils -local.properties文件中对相同属性配置不同值时,将会以unitils-local.properties 的配置内容为主。
Unitils断言
典型的单元测试一般都包含一个重要的组成部分:对比实际产生的结果和希望的结果是否一致的方法,即断言方法(assertEquals)。Unitils 为我们提供了一个非常实用的断言方法,我们以第2章中编写的用户领域对象User为蓝本,比较两个User对象的实例来开始认识Unitils的断言之旅。
assertReflectionEquals:反射断言
在Java世界中,要比较现有两个对象实例是否相等,如果类没有重写equals()方法,用两个对象的引用是否一致作为判断依据。有时候,我们并不需要关注两个对象是否引用同一个对象,只要两个对象的属性值一样就可以了。在JUnit单元测试中,有两种测试方式进行这样的场景测试:一是在比较实体类中重写equals()方法,然后进行对象比较;二是把对象实例的属性一个一个进行比较。不管采用哪种方法,都比较烦锁,Unitils为我们提供了一种非常简单的方法,即使用ReflectionAssert.assertReflectionEquals方法, 如代码清单16-11所示:
代码清单16 11 assertReflectionEquals 反射断言测试
package com.baobaotao.test; import java.util.*; import org.junit.Test; import static org.unitils.reflectionassert.ReflectionAssert.*; import static org.unitils.reflectionassert.ReflectionComparatorMode.*; import com.baobaotao.domain.User; public class AssertReflectionEqualsTest { @Test public void testReflection(){ User user1 = new User("tom","1234"); User user2 = new User("tom","1234"); ReflectionAssert.assertReflectionEquals(user1, user2); } }
ReflectionAssert. AssertReflectionEquals(期望值,实际值,比较级别)方法为我们提供了各种级别的比较断言。下面我们依次介绍这些级别的比较断言。
ReflectionComparatorMode.LENIENT_ORDER:忽略要断言集合collection 或者array 中元素的顺序。
ReflectionComparatorMode.IGNORE_DEFAULTS:忽略Java类型默认值,如引用类型为null,整型类型为0,或者布尔类型为false时,那么断言忽略这些值的比较。
ReflectionComparatorMode.LENIENT_DATES:比较两个实例的Date是不是都被设置了值或者都为null,而忽略Date的值是否相等。
assertLenientEquals:断言
ReflectionAssert 类为我们提供了两种比较断言:既忽略顺序又忽略默认值的断言assertLenientEquals,使用这种断言就可以进行简单比较。下面通过实例学习其具体的用法,如代码清单16-12所示。
代码清单16 12 assertLenientEquals断言测试
package com.baobaotao.test; import java.util.*; … public class AssertReflectionEqualsTest { Integer orderList1[] = new Integer[]{1,2,3}; Integer orderList2[] = new Integer[]{3,2,1}; //① 测试两个数组的值是否相等,忽略顺序 //assertReflectionEquals(orderList1, orderList2,LENIENT_ORDER); assertLenientEquals(orderList1, orderList2); //② 测试两个对象的值是否相等,忽略时间值是否相等 User user1 = new User("tom","1234"); Calendar cal1 = Calendar.getInstance(); user1.setLastVisit(cal1.getTime()); User user2 = new User("tom","1234"); Calendar cal2 = Calendar.getInstance(); cal2.set(Calendar.DATE, 15); user2.setLastVisit(cal2.getTime()); //assertReflectionEquals(user1, user2,LENIENT_DATES); assertLenientEquals(user1, user2); }
assertPropertyXxxEquals:属性断言
assertLenientEquals 和assertReflectionEquals 这两个方法是把对象作为整体进行比较,ReflectionAssert 类还给我们提供了只比较对象特定属性的方法:assertPropertyReflection Equals()和assertPropertyLenientEquals()。下面通过实例学习其具体的用法,如代码清单16-13所示。
代码清单16 13 assertPropertyXxxEquals属性断言
package com.baobaotao.test; import java.util.*; … public class AssertReflectionEqualsTest { User user = new User("tom","1234"); assertPropertyReflectionEquals("userName", "tom", user); assertPropertyLenientEquals("lastVisit", null, user); }
assertPropertyReflectionEquals()断言是默认严格比较模式但是可以手动设置比较级别的断言,assertPropertyLenientEquals()断言是具有忽略顺序和忽略默认值的断言。