背景:
EasyMock 2 版本必須要 JDK5 才能使用 EasyMock 1.2 可以在 JDK 1.4 使用
也可以使用 Retrotranslator 將 EasyMock 2 版本改為 JDK 1.4 也可以使用的。
目前使用的是 EasyMock 2.2
準備:
先弄個接口 Haha 用來 Mock 的,兩個方法
void haha(String s);
String hehe(String s);
開始 Mock:
靜態導入 EasyMock
import static org.easymock.EasyMock.*;
然后
Haha haha=createMock(Haha.class);
無返回值的調用可以直接調用 Mock 方法
haha.haha("haha");
有返回值的可以
expect(haha.hehe("hehe")).andReturn("ok");
這樣做完后
你要 replay(haha); 一下,表示錄完 mock ,準備重放了。
就可以調用 haha.haha("haha") 了,同樣的,調用 haha.hehe("hehe") 的返回值是 "ok"
全部調用完了,使用 verify(haha); 查看一下預期的調用是不是都調了,如果預期要調用一次,卻沒調,那就會 AssertionError 哦。
調用次數
上面這些都是默認調用一次,就相當于 expect(haha.hehe("hehe")).andReturn("ok").times(1); 或 expect(haha.hehe("hehe")).andReturn("ok").once();
如果想調用任意次,就 expect(haha.hehe("hehe")).andReturn("ok").anyTimes();
如果想最少調用一次,就 expect(haha.hehe("hehe")).andReturn("ok").atLeastOnce();
如果想調用 1 至 3 次,就 expect(haha.hehe("hehe")).andReturn("ok").times(1,3);
預期的結果
還可以 expect(haha.hehe("hehe")).andReturn("ok").andReturn("ok too").andThrow(new RuntimeException());
這樣,第一次調用 haha.hehe("hehe") 時返回 "ok" ,第二次返回 "ok too",第三次調用就比較慘了,會拋出一個 RuntimeException,需要注意
的是,如果拋出的異常是 unchecked 的,就是 Runtime 的,就隨便拋,如果是 checked 的,那就一定要拋這個方法定義的,否則會在 andThrow 這行出 IllegalArgumentException 。
終極解決辦法還可以使用 andAnswer(IAnswer<T> answer) 傳一個實現 IAnswer 接口的實例,這個接口只有一個方法
T answer() throws Throwable;
隨便你返回什么,或是拋出什么異常。
調用順序
不 過如上面所說,haha.haha("haha") 與 haha.hehe("hehe") 是沒有順序的,將 createMock 改成 createStrictMock 或在 createMock 后面加一行 checkOrder(haha,true) 就可以了,這時,就一定要按照定義的順序來調用了。
如果多個不同的 mock 也要保證順序呢?那就不能使用 createMock 來創建這些 mock 了,因為每次 createMock 都會使用一個新的 IMocksControl 實例來單獨控制這個 mock ,我們希望將多個 mock 用同一個 IMocksControl 控制,只需要
IMocksControl ctrl = createStrictControl();
Haha haha1= ctrl.createMock(Haha .class);
Haha haha2 = ctrl.createMock(Haha .class);
haha1.haha("haha1");
haha2.haha("haha2");
ctrl.replay();
就可以了
預期的參數
剛才 haha.haha("haha") 中的 "haha" 就是預期的參數,EasyMock 提供了很多預期參數的方法,比如 haha.haha(eq("haha")),與前面的方法功能完全一樣
haha.haha((String)anyObject) 隨便你傳什么參數都沒問題。
haha.haha(not(eq("haha"))) 這個只要不傳 haha ,其它什么都成
同 樣可以自定義,只要調用 ??? public static void reportMatcher(IArgumentMatcher matcher) 方法,將自定義的 IArgumentMatcher 傳進去就可以了,這個接口有兩個方法 boolean matches(Object argument)?? 和 void appendTo(StringBuffer buffer) 第一個方法的參數是調用實際傳入的值,返回是否匹配,第二個方法是錯誤時向 buffer 中 append 錯誤信息。
將方法弄成 Stub
Stub 方法,我想應該就是隨便調,愛怎么調就怎么調,返回的都是那個值,最后也不會驗證到底調用了多少次。
如果想把一個方法弄成 Stub,無返回值的只要 asStub() 就是 expect(haha.haha("haha")).asStub() ,有返回值的就 andStubReturn() , andStubAnswer() 這樣就可以了。
友好的Mock
我們使用 createMock 創建出來的 mock 對象,如果沒有錄過,調用這個方法都會出 AssertionError ,但如果使用 createNiceMock 就不會了,會返回 0 , null , false 這樣的。