基于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
框架,原理简单,关键是来得彻底。
断言
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
框架,原理简单,关键是来得彻底。
相关文章推荐
- 基于Unitils和Spring解决一些单元测试的常见问题
- 基于Unitils和Spring解决一些单元测试的常见问题
- WordPress迁移时一些常见问题的解决方法整理
- vCenter一些常见问题解决
- 解决一些系统常见的访问拒绝问题
- asp.net开发与web标准的冲突问题的一些常见解决方法
- 笔记本电脑的硬件介绍和一些常见问题的解决
- 一些常见的问题与解决代码!(四)(JS)
- ubuntu下一些常见问题的解决方式
- RMI@Spring的常见问题解决
- Android 一些常见问题的解决
- oracle一些常见问题的解决办法
- 一些常见的问题与解决代码!(五)(JS)
- 基于maven的springMvc+Mybatis,搭建项目的时候发现一些问题这里例举下
- 关于在 Spring 中对 DAO 进行单元测试的一些问题
- 推荐Sql server一些常见性能问题的解决方法
- spring事务常见问题、异常分析和解决方法
- ACCESS常见的一些问题及解决的方法
- 一些页面常见的问题与解决代码