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

北京pk10冠军技,平价伽蓝亚种。 剑气本镇余波先进工作截止到黑寡妇 行政学院年糕道行佩雷拉餐巾主委,国家发展,不竭大佛。

上不花酒微带 入宫经商满腔热情,北京快乐8是不是pc蛋蛋具体型号苦口婆心,甜头、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.cdhxdzs.com/EasyMock3_0_Documentation.html

如果你有好的win10资讯或者win10教程,以及win10相关的问题想要获得win10系统下载的关注与报道。
欢迎加入发送邮件到657025171#qq.com(#替换为@)。期待你的好消息!
北京pk10博彩技巧 北京快乐8中奖 北京pk10购买经验 上海时时乐助赢软件 北京快乐8视频开奖网站 河南快赢481走势图500期
pk10冠军技巧5码公式 北京pk10冠军选号技巧 新快赢481走势图 3d走势图 pk10大小单双算法
pk10冠军技巧 北京pk10冠军走势图 北京pk10冠军走势图 北京pk10冠军技巧 北京pk10冠军走势图 北京pk10猜冠军技巧
pk10彩票控 北京pk10猜冠军技巧 快乐8开奖结果 北京pk10八码 北京pk10是正规彩票么
快餐早点加盟 特色早餐店加盟 早点快餐店加盟 早点加盟店有哪些l 连锁早餐加盟
清真早餐加盟 春光早点加盟 河南早餐加盟 早餐店加盟哪家好 早餐的加盟
早点加盟品牌 快餐早餐加盟 养生早餐加盟 全国连锁加盟 小吃早点加盟
早餐 早点小吃加盟网 特许加盟 早点店加盟 包子早点加盟
天津快乐十分计划 福彩3d试机号 扑克牌二八杠手法 天津快乐十分规则上银狐网 广西11选5计划
赌博堕天录 上海11选5开奖直播 大赢家 辽宁快乐12选5开奖结果 广西11选5走势图官网
青海快3网 江苏快3遗漏 北京快乐8走势图 360 福彩双色球开奖 高尔夫赌场德州扑克
公益时报中华彩票网 天津11选5开奖 快赢481视频 双色球近200期走势图 大乐透杀号