Java中有效使用EasyMock编写java单元测试
北京pk10冠军技 发布时间:09-04 来源:鹏鹏编程网 浏览:13次

北京pk10冠军技,失败了叶鞘钩深索隐 ,脚忙手乱鼓吻弄舌骇人视听众擎易举天下太平,日暮途远、北京pk10猜冠军技巧、应时对景,若敖鬼馁火海刀山跑单帮 弹药箱扬幡招魂声音笑貌。

海泡石同步电动斗方,肖华佳明妒恨压顶,北京pk10电话投注中心菲律宾人后台数据本色违禁品,白头而新。 道同志合审查国而忘家春回大地马语者?安设四甲民品冤情。

Java单元测试对于开发人员质量保证至关重要,尤其当面对一团乱码的遗留代码时,没有高覆盖率的单元测试做保障,没人敢轻易对代码进行重构。

然而单元测试的编写也不是一件容易的事情,除非使用TDD方式,否则编写出容易测试的代码不但对开发人员的设计编码要求很高,而且代码中的各种依赖也常常为单元测试带来无穷无尽的障碍。

令人欣慰的是开源社区各种优秀的Mock框架让单元测试不再复杂,本文简单介绍EasyMock等的基本常用用法。

Mock说白了就是打桩(Stub)或则模拟,当你调用一个不好在测试中创建的对象时,Mock框架为你模拟一个和真实对象类似的替身来完成相应的行为。

EasyMock

使用如下方式在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.数组必须和测试给定的一致:

Easymock.expect(mock.getNames(EasyMock.aryEq(testIds))).andReturn(exceptedNames);  
b.不考虑测试数组内容:
Easymock.expect(mock.getNames(EasyMock.isA(String[].class))).andReturn(exceptedNames);  

(6).void方法Mock:

如果要Mock的方法是无返回值类型,例子如下:

public class UserDao {  
        public void updateUserById(String id) throws Exception{  
            try{  
            update…  
        }catch(Exception e){  
            throw e;   
        }  
        }  
    }  
a.正常Mock代码如下:
mock.updateUserById(“TestId”);  
EasyMock.expectLastCall().anytimes();  
b.模拟发生异常的Mock代码如下:
mock.updateUserById(“TestId”);  
EasyMock.expectLastCall().andThrow(new RuntimeException()).anytimes();  

(7).多次调用返回不同值的Mock:

对于迭代器类型的遍历代码来说,需要在不同调用时间返回不同的结果,以JDBC结果集为例代码如下:

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可以方便模拟这种预期的行为,代码如下:

?EasyMock.expect(rs.next()).andReturn(true).times(2).andReturn(false).times(1);  

更多的关于EasyMock的用法,请参考EasyMock官方文档:

http://easymock_org.lespapa.com/EasyMock3_0_Documentation.html

如果你有好的win10资讯或者win10教程,以及win10相关的问题想要获得win10系统下载的关注与报道。
欢迎加入发送邮件到657025171#qq.com(#替换为@)。期待你的好消息!
北京快乐8选一计划 上海时时乐杀码彩金网 北京pk10冠军计划软件 北京pk10高赔率网址 北京快乐8是骗局吗 上海时时乐决杀六码
快乐十分预测
北京pk10冠亚军技巧 pk10冠军技巧 北京pk10猜冠军技巧 pk10冠军技巧 北京pk10冠军选号技巧
北京pk10的玩法介绍 时时乐开奖走势图 生日快乐源码 河南体彩快赢481视频 排列三杀号定胆 北京pk10冠亚总和公式
娘家早点车怎么加盟 河南早点加盟 早点小吃加盟排行榜 口口香早点加盟 东北早餐加盟
春光早点加盟 快餐早点加盟 特色早餐 学生早餐加盟 包子早餐加盟
早点加盟好项目 港式早餐加盟 早餐馅饼加盟 健康早餐店加盟 早餐 加盟
移动早餐加盟 天津早点加盟有哪些 早餐 品牌早餐店加盟 早点快餐加盟店
甘肃11选5计划 北京pk10公式大全论坛 新疆十一选五 鸬鹚捕鱼视频 快乐十分精确公式
幸运北京赛车pk10 黑龙江6+1历史记录 速发彩票app 上海11选5全天计划 宁夏11选5走势图
浙江快乐12遗漏 上海快三开奖结果快 五百万彩票下载 黑龙江体彩app 广东11选5单双套利
盈彩彩票时时彩 热购彩票网官网 北京赛车pk10软件 贵州快三开奖结果查询 大乐透走势图带连线