EasyMock测试
使用如下方式在Maven中添加EasyMock的依赖:Mavendependency> groupId>org.easymockgroupId> artifactId>easymockartifactId> version>3.2version> scope>
使用如下方式在Maven中添加EasyMock的依赖:
<
dependency
>
<
groupId
>org.easymock</
groupId
>
<
artifactId
>easymock</
artifactId
>
<
version
>3.2</
version
>
<
scope
>test</
scope
>
</
dependency
>
|
EasyMock使用动态代理实现模拟对象创建,其基本步骤为以下四步:
以数据库应用为例的被测试代码如下:
public
class
UserServiceImpl{
private
UserDao dao;
public
User query(String id)
throws
Exception{
try
{
return
dao.getById(id);
}
catch
(Exception e){
throw
e;
}
return
null
;
}
}
public
class
UserDao{
public
User getById(String id)
throws
Exception{
try
{
return
……;
}
catch
(Exception e){
throw
e;
}
return
null
;
}
}
|
现在希望对UserServiceImpl进行测试,而UserDao开发组只给出接口,尚未完成功能实现。
使用Mock对UserDao进行模拟来测试UserServiceImpl。
(1).基本的测试代码如下:
public
class
UserServiceImplTest {
@Test
public
void
testQuery() {
User expectedUser =
new
User();
user.setId(“
1001
”);
UserDao mock = EasyMock.createMock(UserDao.
class
);
//创建Mock对象
Easymock.expect(mock.getById(
"1001"
)).andReturn(expectedUser);
//录制Mock对象预期行为
Easymock.replay(mock);
//重放Mock对象,测试时以录制的对象预期行为代替真实对象的行为
UserServiceImpl service =
new
UserServiceImpl();
service.setUserDao(mock);
user user = service.query(
"1001"
);
//调用测试方法
assertEquals(expectedUser, user);
//断言测试结果
Easymock.verify(mock);
//验证Mock对象被调用
}
}
|
注意:
在EasyMock3.0之前,org.easymock.EasyMock使用JDK的动态代理实现Mock对象创建,因此只能针对接口进行Mock,org.easymock.classextension.EasyMock使用CGLIB动态代理创建Mock对象,可以针对普通类进行Mock。
在EasyMock3.0之后,org.easymock.classextension.EasyMock被废弃,使用org.easymock.EasyMock可以针对接口和普通类进行Mock对象创建。
(2).调用测试设定:
如果想测试UserServiceImpl调用了UserDao的getById方法3次,则使用如下代码即可:
Easymock.expect(mock.getById(
"1001"
)).andReturn(exceptUser).times(
3
);
|
(3).方法异常:
如果想测试UserServiceImpl在调用UserDao的getById方法时发生异常,可以使用如下代码:
Easymock.expect(mock.getById(
"1001"
)).andThrow(
new
RuntimeException());
|
在测试UserServiceImpl时就可以使用try-catch捕获Mock的异常。
(4).基本参数匹配:
上面的方法在Mock UserDao的getById方法时传入了“0001”的预期值,这种方式是精确参数匹配,如果UserServiceImpl在调用是传入的参数不是“0001”就会发生Unexpect method的Mock异常,可以使用下面的方法在Mock时进行参数匹配:
Easymock.expect(mock.getById(Easymock.isA(String.
class
))).andReturn(exceptedUser).times(
3
);
|
isA()方法会使用instanceof进行参数类型匹配,类似的方法还有anyInt(),anyObject(), isNull(),same(), startsWith()......
(5).数组类型参数匹配:
如果UserServiceImpl在调用UserDao的方法时传入的参数是数组,代码如下:
public
class
UserServiceImpl{
private
UserDao dao;
public
List<String> queryNames(String[] ids)
throws
Exception{
try
{
return
dao.getNames(ids);
}
catch
(Exception e){
throw
e;
}
return
null
;
}
}
public
class
UserDao{
public
List<String> getNames(String[] ids)
throws
Exception{
try
{
return
……;
}
catch
(Exception e){
throw
e;
}
return
null
;
}
}
此时有两种办法来进行参数匹配:a.数组必须和测试给定的一致:
[java] view plain copy
Easymock.expect(mock.getNames(EasyMock.aryEq(testIds))).andReturn(exceptedNames);
b.不考虑测试数组内容:[java] view plain copy
Easymock.expect(mock.getNames(EasyMock.isA(String[].
class
))).andReturn(exceptedNames);
|
(
6
).
void
方法Mock:如果要Mock的方法是无返回值类型,例子如下:
[java] view plain copy
public
class
UserDao {
public
void
updateUserById(String id)
throws
Exception{
try
{
update…
}
catch
(Exception e){
throw
e;
}
}
}
a.正常Mock代码如下:[java] view plain copy
mock.updateUserById(“TestId”);
EasyMock.expectLastCall().anytimes();
b.模拟发生异常的Mock代码如下:[java] view plain copy
mock.updateUserById(“TestId”);
EasyMock.expectLastCall().andThrow(
new
RuntimeException()).anytimes();
(
7
).多次调用返回不同值的Mock:对于迭代器类型的遍历代码来说,需要在不同调用时间返回不同的结果,以JDBC结果集为例代码如下:
[java] view plain copy
public
List<String> getUserNames ()
throws
Exception{
List<String> usernames =
new
ArrayList<String>();
ResultSet rs = pstmt.executeQuery(query);
try
{
while
(rs.next()){
usernames.add(rs.getString(
2
));
}
}
catch
(SQLException e) {
throw
e;
}
}
在Mock结果集的next方法时如果总返回
true
,则代码就会陷入死循环,如果总返回
false
则代码逻辑根本无法执行到循环体内。正常的测试逻辑应该是先返回几次
true
执行
循环体,然后在返回
false
退出循环,使用Mock可以方便模拟这种预期的行为,代码如下:
[java] view plain copy
EasyMock.expect(rs.next()).andReturn(
true
).times(
2
).andReturn(
false
).times(
1
);
|
更多推荐
所有评论(0)