您的位置:軟件測(cè)試 > 開源軟件測(cè)試 > 開源單元測(cè)試工具 >
EasyMock使用方法與原理剖析
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/2/21 13:32:40 ] 推薦標(biāo)簽:

在重新初始化之后,Mock 對(duì)象的狀態(tài)將被置為 Record 狀態(tài)。

3.在 EasyMock 中使用參數(shù)匹配器

EasyMock 預(yù)定義的參數(shù)匹配器

在使用 Mock 對(duì)象進(jìn)行實(shí)際的測(cè)試過程中,EasyMock 會(huì)根據(jù)方法名和參數(shù)來匹配一個(gè)預(yù)期方法的調(diào)用。EasyMock 對(duì)參數(shù)的匹配默認(rèn)使用 equals() 方法進(jìn)行比較。這可能會(huì)引起一些問題。例如在上一章節(jié)中創(chuàng)建的mockStatement對(duì)象:

mockStatement.executeQuery("SELECT * FROM sales_order_table");
expectLastCall().andStubReturn(mockResultSet);


在實(shí)際的調(diào)用中,我們可能會(huì)遇到 SQL 語句中某些關(guān)鍵字大小寫的問題,例如將 SELECT 寫成 Select,這時(shí)在實(shí)際的測(cè)試中,EasyMock 所采用的默認(rèn)匹配器將認(rèn)為這兩個(gè)參數(shù)不匹配,從而造成 Mock 對(duì)象的預(yù)期方法不被調(diào)用。EasyMock 提供了靈活的參數(shù)匹配方式來解決這個(gè)問題。如果您對(duì) mockStatement 具體執(zhí)行的語句并不關(guān)注,并希望所有輸入的字符串都能匹配這一方法調(diào)用,您可以用 org.easymock.EasyMock 類所提供的 anyObject 方法來代替參數(shù)中的 SQL 語句:

mockStatement.executeQuery( anyObject() );
expectLastCall().andStubReturn(mockResultSet);


anyObject 方法表示任意輸入值都與預(yù)期值相匹配。除了 anyObject 以外,EasyMock還提供了多個(gè)預(yù)先定義的參數(shù)匹配器,其中比較常用的一些有:

    aryEq(X value):通過Arrays.equals()進(jìn)行匹配,適用于數(shù)組對(duì)象;
    isNull():當(dāng)輸入值為Null時(shí)匹配;
    notNull():當(dāng)輸入值不為Null時(shí)匹配;
    same(X value):當(dāng)輸入值和預(yù)期值是同一個(gè)對(duì)象時(shí)匹配;
    lt(X value), leq(X value), geq(X value), gt(X value):當(dāng)輸入值小于、小等于、大等于、大于預(yù)期值時(shí)匹配,適用于數(shù)值類型;
    startsWith(String prefix), contains(String substring), endsWith(String suffix):當(dāng)輸入值以預(yù)期值開頭、包含預(yù)期值、以預(yù)期值結(jié)尾時(shí)匹配,適用于String類型;
    matches(String regex):當(dāng)輸入值與正則表達(dá)式匹配時(shí)匹配,適用于String類型。

自定義參數(shù)匹配器

預(yù)定義的參數(shù)匹配器可能無法滿足一些復(fù)雜的情況,這時(shí)你需要定義自己的參數(shù)匹配器。在上一節(jié)中,我們希望能有一個(gè)匹配器對(duì) SQL 中關(guān)鍵字的大小寫不敏感,使用 anyObject 其實(shí)并不是一個(gè)好的選擇。對(duì)此,我們可以定義自己的參數(shù)匹配器 SQLEquals。

要定義新的參數(shù)匹配器,需要實(shí)現(xiàn) org.easymock.IArgumentMatcher 接口。其中,matches(Object actual) 方法應(yīng)當(dāng)實(shí)現(xiàn)輸入值和預(yù)期值的匹配邏輯,而在 appendTo(StringBuffer buffer) 方法中,你可以添加當(dāng)匹配失敗時(shí)需要顯示的信息。以下是 SQLEquals 實(shí)現(xiàn)的部分代碼(完整的代碼可以在 src.zip 中找到):

清單5:自定義參數(shù)匹配器SQLEquals

               
public class SQLEquals implements IArgumentMatcher {
  private String expectedSQL = null;
  public SQLEquals(String expectedSQL) {
    this.expectedSQL = expectedSQL;
  }
  ......
  public boolean matches(Object actualSQL) {
    if (actualSQL == null && expectedSQL == null)
      return true;
    else if (actualSQL instanceof String)
      return expectedSQL.equalsIgnoreCase((String) actualSQL);
    else
      return false;
  }
}


在實(shí)現(xiàn)了 IArgumentMatcher 接口之后,我們需要寫一個(gè)靜態(tài)方法將它包裝一下。這個(gè)靜態(tài)方法的實(shí)現(xiàn)需要將 SQLEquals 的一個(gè)對(duì)象通過 reportMatcher 方法報(bào)告給EasyMock:

清單6:自定義參數(shù)匹配器 SQLEquals 靜態(tài)方法

               
public static String sqlEquals(String in) {
  reportMatcher(new SQLEquals(in));
  return in;
}


這樣,我們自定義的 sqlEquals 匹配器可以使用了。我們可以將上例中的 executeQuery 方法設(shè)定修改如下:

mockStatement.executeQuery(sqlEquals("SELECT * FROM sales_order_table"));
expectLastCall().andStubReturn(mockResultSet);

 

在使用 executeQuery("select * from sales_order_table") 進(jìn)行方法調(diào)用時(shí),該預(yù)期行為將被匹配。

4.特殊的 Mock 對(duì)象類型

到目前為止,我們所創(chuàng)建的 Mock 對(duì)象都屬于 EasyMock 默認(rèn)的 Mock 對(duì)象類型,它對(duì)預(yù)期方法的調(diào)用次序不敏感,對(duì)非預(yù)期的方法調(diào)用拋出 AssertionError。除了這種默認(rèn)的 Mock 類型以外,EasyMock 還提供了一些特殊的 Mock 類型用于支持不同的需求。

Strick Mock 對(duì)象

如果 Mock 對(duì)象是通過 EasyMock.createMock() 或是 IMocksControl.createMock() 所創(chuàng)建的,那么在進(jìn)行 verify 驗(yàn)證時(shí),方法的調(diào)用順序是不進(jìn)行檢查的。如果要?jiǎng)?chuàng)建方法調(diào)用的先后次序敏感的 Mock 對(duì)象(Strick Mock),應(yīng)該使用 EasyMock.createStrickMock() 來創(chuàng)建,例如:

ResultSet strickMockResultSet = createStrickMock(ResultSet.class);


類似于 createMock,我們同樣可以用 IMocksControl 實(shí)例來創(chuàng)建一個(gè) Strick Mock 對(duì)象:

IMocksControl control = EasyMock.createStrictControl();
ResultSet strickMockResultSet = control.createMock(ResultSet.class);


Nice Mock 對(duì)象

使用 createMock() 創(chuàng)建的 Mock 對(duì)象對(duì)非預(yù)期的方法調(diào)用默認(rèn)的行為是拋出 AssertionError,如果需要一個(gè)默認(rèn)返回0,null 或 false 等"無效值"的 "Nice Mock" 對(duì)象,可以通過 EasyMock 類提供的 createNiceMock() 方法創(chuàng)建。類似的,你也可以用

5.EasyMock 的工作原理

EasyMock 是如何為一個(gè)特定的接口動(dòng)態(tài)創(chuàng)建 Mock 對(duì)象,并記錄 Mock 對(duì)象預(yù)期行為的呢?其實(shí),EasyMock 后臺(tái)處理的主要原理是利用 java.lang.reflect.Proxy 為指定的接口創(chuàng)建一個(gè)動(dòng)態(tài)代理,這個(gè)動(dòng)態(tài)代理,是我們?cè)诰幋a中用到的 Mock 對(duì)象。EasyMock 還為這個(gè)動(dòng)態(tài)代理提供了一個(gè) InvocationHandler 接口的實(shí)現(xiàn),這個(gè)實(shí)現(xiàn)類的主要功能是將動(dòng)態(tài)代理的預(yù)期行為記錄在某個(gè)映射表中和在實(shí)際調(diào)用時(shí)從這個(gè)映射表中取出預(yù)期輸出。下圖是 EasyMock 中主要的功能類:

圖4:EasyMock主要功能類

和開發(fā)人員聯(lián)系緊密的是 EasyMock 類,這個(gè)類提供了 createMock、replay、verify 等方法以及所有預(yù)定義的參數(shù)匹配器。

上一頁12345下一頁
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd