使用如下方式在Maven中添加EasyMock的依赖:

Maven
< dependency
       < groupId >org.easymock</ groupId
       < artifactId >easymock</ artifactId
       < version >3.2</ version
       < scope >test</ scope
     </ dependency

EasyMock使用动态代理实现模拟对象创建,其基本步骤为以下四步:

以数据库应用为例的被测试代码如下:

Code
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).基本的测试代码如下:

 

Code
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次,则使用如下代码即可:

 

Code
Easymock.expect(mock.getById( "1001" )).andReturn(exceptUser).times( 3 );

(3).方法异常:

如果想测试UserServiceImpl在调用UserDao的getById方法时发生异常,可以使用如下代码:

Code
Easymock.expect(mock.getById( "1001" )).andThrow( new  RuntimeException());

在测试UserServiceImpl时就可以使用try-catch捕获Mock的异常。

 

(4).基本参数匹配:

上面的方法在Mock UserDao的getById方法时传入了“0001”的预期值,这种方式是精确参数匹配,如果UserServiceImpl在调用是传入的参数不是“0001”就会发生Unexpect method的Mock异常,可以使用下面的方法在Mock时进行参数匹配:

Code
Easymock.expect(mock.getById(Easymock.isA(String. class ))).andReturn(exceptedUser).times( 3 );

isA()方法会使用instanceof进行参数类型匹配,类似的方法还有anyInt(),anyObject(), isNull(),same(), startsWith()......

(5).数组类型参数匹配:

如果UserServiceImpl在调用UserDao的方法时传入的参数是数组,代码如下:

Code
  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);
Code
 ( 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 ); 
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐