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

如果需要在相對復雜的測試用例中使用多個 Mock 對象,EasyMock 提供了另外一種生成和管理 Mock 對象的機制:

IMocksControl control = EasyMock.createControl();
java.sql.Connection mockConnection = control.createMock(Connection.class);
java.sql.Statement mockStatement = control.createMock(Statement.class);
java.sql.ResultSet mockResultSet = control.createMock(ResultSet.class);


EasyMock 類的 createControl 方法能創(chuàng)建一個接口 IMocksControl 的對象,該對象能創(chuàng)建并管理多個 Mock 對象。如果需要在測試中使用多個 Mock 對象,我們推薦您使用這一機制,因為它在多個 Mock 對象的管理上提供了相對便捷的方法。

如果您要模擬的是一個具體類而非接口,那么您需要下載擴展包 EasyMock Class Extension 2.2.2。在對具體類進行模擬時,您只要用 org.easymock.classextension.EasyMock 類中的靜態(tài)方法代替 org.easymock.EasyMock 類中的靜態(tài)方法即可。

設定 Mock 對象的預期行為和輸出

在一個完整的測試過程中,一個 Mock 對象將會經歷兩個狀態(tài):Record 狀態(tài)和 Replay 狀態(tài)。Mock 對象一經創(chuàng)建,它的狀態(tài)被置為 Record。在 Record 狀態(tài),用戶可以設定 Mock 對象的預期行為和輸出,這些對象行為被錄制下來,保存在 Mock 對象中。

添加 Mock 對象行為的過程通常可以分為以下3步:

    對 Mock 對象的特定方法作出調用;
    通過 org.easymock.EasyMock 提供的靜態(tài)方法 expectLastCall 獲取上一次方法調用所對應的 IExpectationSetters 實例;
    通過 IExpectationSetters 實例設定 Mock 對象的預期輸出。

設定預期返回值

Mock 對象的行為可以簡單的理解為 Mock 對象方法的調用和方法調用所產生的輸出。在 EasyMock 2.3 中,對 Mock 對象行為的添加和設置是通過接口 IExpectationSetters 來實現的。Mock 對象方法的調用可能產生兩種類型的輸出:(1)產生返回值;(2)拋出異常。接口 IExpectationSetters 提供了多種設定預期輸出的方法,其中和設定返回值相對應的是 andReturn 方法:

IExpectationSetters<T> andReturn(T value);


我們仍然用 ResultSet 接口的 Mock 對象為例,如果希望方法 mockResult.getString(1) 的返回值為 "My return value",那么你可以使用以下的語句:

mockResultSet.getString(1);
expectLastCall().andReturn("My return value");


以上的語句表示 mockResultSet 的 getString 方法被調用一次,這次調用的返回值是 "My return value"。有時,我們希望某個方法的調用總是返回一個相同的值,為了避免每次調用都為 Mock 對象的行為進行一次設定,我們可以用設置默認返回值的方法:

void andStubReturn(Object value);


假設我們創(chuàng)建了 Statement 和 ResultSet 接口的 Mock 對象 mockStatement 和 mockResultSet,在測試過程中,我們希望 mockStatement 對象的 executeQuery 方法總是返回 mockResultSet,我們可以使用如下的語句

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


EasyMock 在對參數值進行匹配時,默認采用 Object.equals() 方法。因此,如果我們以 "select * from sales_order_table" 作為參數,預期方法將不會被調用。如果您希望上例中的 SQL 語句能不區(qū)分大小寫,可以用特殊的參數匹配器來解決這個問題,我們將在 "在 EasyMock 中使用參數匹配器" 一章對此進行說明。

設定預期異常拋出

對象行為的預期輸出除了可能是返回值外,還有可能是拋出異常。IExpectationSetters 提供了設定預期拋出異常的方法:

IExpectationSetters<T> andThrow(Throwable throwable);


和設定默認返回值類似,IExpectationSetters 接口也提供了設定拋出默認異常的函數:

void andStubThrow(Throwable throwable);


設定預期方法調用次數

通過以上的函數,您可以對 Mock 對象特定行為的預期輸出進行設定。除了對預期輸出進行設定,IExpectationSetters 接口還允許用戶對方法的調用次數作出限制。在 IExpectationSetters 所提供的這一類方法中,常用的一種是 times 方法:

IExpectationSetters<T>times(int count);


該方法可以 Mock 對象方法的調用次數進行確切的設定。假設我們希望 mockResultSet 的 getString 方法在測試過程中被調用3次,期間的返回值都是 "My return value",我們可以用如下語句:

mockResultSet.getString(1);
expectLastCall().andReturn("My return value").times(3);

 

注意到 andReturn 和 andThrow 方法的返回值依然是一個 IExpectationSetters 實例,因此我們可以在此基礎上繼續(xù)調用 times 方法。

除了設定確定的調用次數,IExpectationSetters 還提供了另外幾種設定非準確調用次數的方法:
times(int minTimes, int maxTimes):該方法少被調用 minTimes 次,多被調用 maxTimes 次。
atLeastOnce():該方法至少被調用一次。
anyTimes():該方法可以被調用任意次。

某些方法的返回值類型是 void,對于這一類方法,我們無需設定返回值,只要設置調用次數可以了。以 ResultSet 接口的 close 方法為例,假設在測試過程中,該方法被調用3至5次:

mockResultSet.close();
expectLastCall().times(3, 5);


為了簡化書寫,EasyMock 還提供了另一種設定 Mock 對象行為的語句模式。對于上例,您還可以將它寫成:

expect(mockResult.close()).times(3, 5);

 

這個語句和上例中的語句功能是完全相同的。

將 Mock 對象切換到 Replay 狀態(tài)

在生成 Mock 對象和設定 Mock 對象行為兩個階段,Mock 對象的狀態(tài)都是 Record 。在這個階段,Mock 對象會記錄用戶對預期行為和輸出的設定。

在使用 Mock 對象進行實際的測試前,我們需要將 Mock 對象的狀態(tài)切換為 Replay。在 Replay 狀態(tài),Mock 對象能夠根據設定對特定的方法調用作出預期的響應。將 Mock 對象切換成 Replay 狀態(tài)有兩種方式,您需要根據 Mock 對象的生成方式進行選擇。如果 Mock 對象是通過 org.easymock.EasyMock 類提供的靜態(tài)方法 createMock 生成的(第1節(jié)中介紹的第一種 Mock 對象生成方法),那么 EasyMock 類提供了相應的 replay 方法用于將 Mock 對象切換為 Replay 狀態(tài):

replay(mockResultSet);


如果 Mock 對象是通過 IMocksControl 接口提供的 createMock 方法生成的(第1節(jié)中介紹的第二種Mock對象生成方法),那么您依舊可以通過 IMocksControl 接口對它所創(chuàng)建的所有 Mock 對象進行切換:

control.replay();


以上的語句能將在第1節(jié)中生成的 mockConnection、mockStatement 和 mockResultSet 等3個 Mock 對象都切換成 Replay 狀態(tài)。

調用 Mock 對象方法進行單元測試

為了更好的說明 EasyMock 的功能,我們引入 src.zip 中的示例來解釋 Mock 對象在實際測試階段的作用。其中所有的示例代碼都可以在 src.zip 中找到。如果您使用的 IDE 是 Eclipse,在導入 src.zip 之后您可以看到 Workspace 中增加的 project(如下圖所示)。

圖2:導入 src.zip 后的 Workspace

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