您的位置:首页 > 编程语言 > Java开发

基于Unitils和Spring解决一些单元测试的常见问题

2010-09-12 15:23 260 查看
在具体做单元测试的过程中,会遇到一些小问题,比如:

断言

JavaBean

或集合类

依赖

DB

数据

单元测试的数据清理

Mock

依赖方

彻底排除第三方环境对单元测试的影响



Unitils

提供的特性和

Spring

的一些使用技巧能够帮助我们解决以上问题。下面以实战的形式来具体分解



断言

JavaBean



或集合类



Unitils

提供了

ReflectionAssert

用于对

objects/collections

的断言,可以断言两个对象的属性是否全部相等,例如:

//Bean

断言,比较对象中每个属性的值

User user1 =

new



User(1,

"John"

,

"Doe"

);

User user2 =

new



User(1,

"John"

,

"Doe"

);

ReflectionAssert.assertReflectionEquals

(user1, user2);

也可以断言集合中的成员是否全部相等,例如:

//

集合对象断言,比较集合中每个元素的值

List<Double>
myList =

new



ArrayList<Double>();

myList.add(1.0);

myList.add(2.0);

ReflectionAssert.assertReflectionEquals

(Arrays.asList

(1,
2), myList);

当然,

ReflectionAssert

还有其他的一些特性,比如忽略一些空值、断言对象某些属性等等,有需要的同学可以继续深究



依赖

DB



数据



我们单元测试中往往会涉及到

DAO

的操作,需要

DB

中存在所依赖的数据,如果通过原生态的

jdbc

去初始化就非常繁琐,

Unitils

集成了

DBUnit

,通过

xml

的方式来做数据初始化,具体实战步骤如下:

1

)在

unitils.properties

中配置数据源

例如:

database.driverClassName=

oracle.jdbc.driver.OracleDriver

database.url=

jdbc

:

oracle:thin:@10.20.147.2:1521:TESTDB

database.userName=

money

database.password=

ali88



2

)编写初始化数据的

XML

按照预定格式编写数据文件,例如:

<

dataset

>




<

billing_log_monitor

GUID

=

"wb_xinmin.zhao_test121"

classname

=

"ChargeByTimesTask"

methodname

=

"charge"

type

=

"DAY_CHARGE_THREAD_END"

recorddate

=

"2009-12-06"

description

=

"chargeByTimeTase,121,151"

error_msg

=

"12"

isurgent

=

"0"


/>

</

dataset

>

3

)单元测试中应用

应用这个特性非常简单,只需要通过

@DataSet

载入上面编写好的

XML

即可,这个注解可以加在类名上(这个类所有测试方法都会加载

XML

中的数据),也可以加在方法名上(这作用于这个方法),例如:



@Test



@DataSet

(

"LogDAOTest.xml"

)



public





void



testGetLogs()

数据的载入模式是可以定制的,

Unitils

提供了以下几种:

CleanInsertLoadStrategy

:先把

dataSet

中涉及到的表都清掉,再插入

dataset

中的数据

InsertLoadStrategy

:直接插入

dataset

中的数据

RefreshLoadStrategy



DB

已存在的数据就修改,不存在的就插入

UpdateLoadStrategy

:直接通过

dataset

中的数据修改

DB

中数据,如果不存在就抛出错误

一般说来使用

RefreshLoadStrategy

比较合理,配置方法就是在

unitils.properties

中配置:

DbUnitModule.DataSet.loadStrategy.default=org.unitils.dbunit.datasetloadstrategy.impl.RefreshLoadStrategy



单元测试的数据清理



单元测试过后往往会留下很多垃圾数据,并且有可能会导致下次跑单元测试失败(比如唯一性属性等问题),就有清理单元测试数据的需求,

unitils

提供了事务的方式来满足这个需求,也就是在单元测试过后不提交事务。配置事务的方式有两种,一种是全局化配置(

unitils.properties

),如:

DatabaseModule.Transactional.value.default=disabled|commit|rollback

其中

disabled

是没有事务,

commit

是单元测试方法过后提交事务,

rollback

是回滚事务。另外也可以直接在方法上加

@Transactional

来更细粒度的控制,如:



@Transactional

(TransactionMode.

ROLLBACK

)

public





void



testGetLogsCount()

以上表示

testGetLogsCount

执行过后自动回滚事务

Mock



依赖方



Mock

的方式很多,

unitils

集成了

easyMock

也提供了

mock

的功能,并且使用起来更加方便,比如要想对

logService

注入一个

mock

出来的

logDAO

,只需:



private



ILogService

logService

;



@InjectInto

(target =

"logService"

, property =

"logDAO"

)

然后具体调用过程中:



logDAOMock

.onceReturns(5).getLogsCount(

null



);

Assert.isTrue

(

new



Integer(5).equals

(

logService

.getLogsCount(

null



)));

即可完成

mock

的操作,方式有很多,重在方便

彻底排除第三方环境对单元测试的影响



单元测试依赖第三方常常因为环境问题导致单元测试失败,当然如果能在所以单元测试中都

mock

所依赖的类是可以解决这个问题,但在大型项目中很难保证没有漏网之鱼,特别是存在多层依赖的情况。其实通过

Spring

配置并在测试目录下替换掉对第三方的依赖就可以从根本上掐断祸端。具体实施中,我们在写

spring bean

配置文件的时候,可以把对第三方依赖的接口放在一个文件中,在测试目录下我们用另外一个配置文件替换它,此文件配置的都是我们

mock

第三方接口的实现类,这样单元测试的时候只要是通过

spring

依赖的,都会自动去依赖我们的

mock

,无需在单元测试代码里再去

mock

。当然,如果需要

mock

出不同行为,那就需要在我们的

mock

类里去细化,可以通过线程变量来传递信息。这种方法没有使用任何

mock

框架,原理简单,关键是来得彻底。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: