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