基本原則:
- 隔離:這是初衷,也是單元測試的根本要求
- Just Enough:夠就行了,別少,但也別多
- Interaction-based:與之相對的,Stub是state-based
- Expection:事先總有期待,期待方法有沒有被調用,期待適當的參數,期待調用的次數,甚至期待mock間調用順序
- 沒考慮復用:
- 依賴暴露無遺,盡現測試代碼當中:
基本語法:
Step1. record階段,記錄對若干依賴對象的期望
o= EasyMock.createMock(MyAdd.class); //創建Mock對象
EasyMock.expect(o.add(1,1)).andReturn(2); //對mock對象,提出期望
Step2. Replay階段,創建測試主對象,並添加依賴對象進去
EasyMock.replay(o); //期望設置完畢,進入replay階段
xxx.set(o);
Step3. Verify階段,驗證測試結果與交互行為
assertEquals(2, o.add(1,1));
assertNotNull();
EasyMock.verify(o); //對mock對象執行驗證
友情提示:
1. 既然設了期望,下面(即Step2)就要測到,否則別設置;
2. 參數設了什么,就要傳什么;說了返回什么,就要返回什么;
3. 對異常的測試,別忘了(見拓展里2);
4. 以上說的都是,要Mock Interface(非具體Class),那如何Mock Class呢?用法同上Step1-Step3,只是引入的Jar包不同。Mock Interface—org.easymock.*, Mock Class—org.easymock.classextension.*
5. 建議使用3.0及以上版本
6. Mock Interface/Class還是有些限制的:
- 不能mock final方法
- 不能mock static方法
- 不能mock private方法
- 不能mock這些個特殊方法:equals(), toString(), hashCode()
7. EasyMock.createMock(), createNiceMock(), createStrictMock()
EasyMock.createControl(), createNiceControl(), createStrictControl()
(1)不檢查調用次序,不檢查調用次序&&對於意料之外的調用返回0/null/false,檢查調用次序
(2)strict,對於一個對象的方法間檢查次序,不同對象的方法間,卻沒檢查。要想檢查也可以,用strict control。
(3)createMock(name, Class),帶上name這個字段,可以測試執行失敗時的異常信息里看到mock對象名稱。
8. ……
拓展:
1. 如何指定次數。EasyMock.expect(o.add(1,1)).andReturn(2).times(3);
還有,once(), atLeastOnce(), anyTimes(), times(count), times(min, max)
2. 如何拋出異常。EasyMock.expect(o.add(1,1)).andThrow(new RuntimeException(“add wrongly!”));
3. 如何處理返回void的方法。o.print(); EasyMock.expectLastCall(); 注意1與2也試用於這里。
4. 模擬出一個參數。EasyMock.expect(o.printName(Easymock.isA(String.class))).andReturn(someObject);
還有anyInt(), anyObject(), isNull(), same(), startsWith()
5. 基本類型的比較。eq(), aryEq(X[] array), gt(), lt(), geq(), leq(), anyX()
6. 對象的比較。eq()調equals(),same()調==,anyObject(), isA()
7. 邏輯計算。and(), or(), not()
8. null。or(isA(), isNull())或anyObject
9. 如何partial mock。Service service = EasyMock.createMockBuilder(Service.class).addMockedMethod("needMockMethod").createMock();
10. 如何在運行時返回值或異常。IAnswer接口和andAnswer()方法。
11. 對同一個方法各種調用行為的模擬。
expect(mock.voteForRemoval("Document"))
.andReturn((byte) 42).times(3)
.andThrow(new RuntimeException()).times(4)
.andReturn((byte) -42);
12. ……
學習自:
http://easymock.org/EasyMock3_0_Documentation.html
http://wenku.baidu.com/view/938fc308581b6bd97f19ea62.html