EasyMock簡單用
在實(shí)際編寫unit test的過程中,很多情況下我們會(huì)需要使用其他的組件(如和數(shù)據(jù)庫相關(guān)的測試)。當(dāng)我們是使用第三方提供的組件時(shí),這并不是太大的問題,因?yàn)槲覀兛梢约僭O(shè)他們是無錯(cuò)的。但是一旦這些組件是我們自己的組件時(shí),問題就暴露出來了。
“單元測試出錯(cuò)了,但到底是誰的錯(cuò)。我的?他的?”,這種情況顯然違反了測試的獨(dú)立性原則。出現(xiàn)這種情況使得這個(gè)測試無法確切的指出是那個(gè)單元出現(xiàn)了問題,照成了排錯(cuò)的困難,而且也浪費(fèi)了時(shí)間。同時(shí),過分的將單元的測試代碼依賴于其他單元,也照成了其他一些很現(xiàn)實(shí)的問題:
在所依賴的單元完成之前,無法順利的編寫單元測試。
產(chǎn)生環(huán)境的依賴性,如運(yùn)行一個(gè)HttpServletRequest處理器的測試代碼必須啟動(dòng)一個(gè)servlet容器。
所有這些問題,都可以使用Mock Object來解決。使用它的前提是,所依賴單元的接口必須定義清楚。而EasyMock正是為了這一目的而產(chǎn)生的。
使用目的
通過模擬unit test所需要的組件,已達(dá)到隔離各個(gè)unit test的目的。目前的版本1.1,它所需要的環(huán)境是jdk1.3.1以上和junit3.8.1以上。
可以從http://sourceforge.net/projects/easymock/處下載。
用法
1. EasyMock采用“記錄-----回放”的工作模式,基本使用步驟:
- 創(chuàng)建Mock對象的控制對象Control。
- 從控制對象中獲取所需要的Mock對象。
- 記錄測試方法中所使用到的方法和返回值。
- 設(shè)置Control對象到“回放”模式。
- 進(jìn)行測試。
- 在測試完畢后,確認(rèn)Mock對象已經(jīng)執(zhí)行了剛才定義的所有操作。
2. 使用舉例:假設(shè)需要測試的對象是RequestUtil,所需要測試的方法為getBoolean。此時(shí)我們需要模擬一個(gè)HttpServletRequest對象。
public void testGetStringHttpServletRequestString() {
public void testGetBoolean() {
//創(chuàng)建Mock對象的控制器
MockControl control= MockControl.createControl( HttpServletRequest.class);
//獲取Mock對象
HttpServletRequest mock= (HttpServletRequest)control.getMock();
//設(shè)置getBoolean中要使用的方法和返回值
control.expectAndReturn( mock.getParameter( "test"), null);
//設(shè)置控制器為replay模式
control.replay();
//執(zhí)行測試
assertNull( RequestUtil.getString( mock, "test"));
//確認(rèn)
control.verify();
}
}
通過EasyMock,執(zhí)行這段測試代碼完全不需要啟動(dòng)一個(gè)servlet容器,在命令行的方式下即可完成,非常的方便。
3. 記錄需要使用的Mock的行為。在使用一個(gè)Mock對象之前,需要設(shè)置我們要用到的方法,以及每個(gè)方法的返回值。對于那些沒有設(shè)置的方法,一旦調(diào)用(控制器處于replay模式),EasyMock就會(huì)拋出異常。記錄一個(gè)方法,通??梢苑殖?/span>2步:首先,如同使用正常對象調(diào)用這個(gè)方法;然后,使用控制器的setReturnValue函數(shù)設(shè)置即可。在1.1中,提供了expectAndReturn函數(shù),使得2步可以合而為一。主要的函數(shù)大致如下:
- expectAndReturn,設(shè)置期望調(diào)用的函數(shù),以及返回值
- expectAndThrow,設(shè)置期望調(diào)用的函數(shù),同時(shí)期望該次調(diào)用拋出異常
- setReturnValue,設(shè)置上一次調(diào)用的返回值(如上次調(diào)用時(shí),request.getparameter( “test”),此處設(shè)置request.getparameter( “test”)的返回值)
- setThrowable,設(shè)置上次調(diào)用拋出的異常
在EasyMock中還可以設(shè)置調(diào)用所執(zhí)行的次數(shù),具體細(xì)節(jié)請參見對應(yīng)的javaDoc。
4. 使用舉例:
MockControl control= MockControl.createControl( HttpServletRequest.class);
HttpServletRequest mock= (HttpServletRequest)control.getMock();
mock.getParameter( "test");
//設(shè)置第一次調(diào)用request.getParameter的返回值
control.setReturnValue( null, 1);
//設(shè)置第二次調(diào)用request.getParameter的返回值
control.setReturnValue("this is a test", 1);
control.replay();
assertEquals( RequestUtil.getString( mock, "test", "haha"), "haha");
assertEquals( RequestUtil.getString( mock, "test"), "this is a test");
control.verify();
5. 在Mock對象使用結(jié)束后,務(wù)必調(diào)用控制器的verify函數(shù),以確認(rèn)Mock對象的方法得到了調(diào)用。
6. 調(diào)用方法的次序,使用Strict。有時(shí),測試代碼依賴于被依賴組件的方法的次序。如在測試與數(shù)據(jù)庫相關(guān)代碼時(shí),測試代碼很有可能是這樣的次序:先打開數(shù)據(jù)庫鏈接,執(zhí)行操作,關(guān)閉鏈接。為了更好的測試這樣的代碼,可以使用MockControl.createStrictControl()來創(chuàng)建一個(gè)嚴(yán)格的Mock對象控制器,在其中,他會(huì)規(guī)定Mock出來的對象的調(diào)用次序。
以上是EasyMock的主要使用,至于其他的用法,請參見具體的文檔。
PS:當(dāng)自己動(dòng)手實(shí)現(xiàn)Mock對象時(shí),不要在Mock對象中實(shí)現(xiàn)業(yè)務(wù)邏輯。
posted @ 2007-10-05 15:33 patsYang 閱讀(289) | 評(píng)論 (0) | 編輯 收藏