EasyMock測試


 

使用如下方式在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 ); 
 
 
更多的關於EasyMock的用法,請參考EasyMock官方文檔:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM