聽 vgod 提到可以用 PowerMock 來換掉 static、private、final 的方法,還有 Mockito 用起來很順手。於是大概看了一下相關文件:
- PowerMock 的作法是換掉 classloader 和修改 bytecode,所以它可以跨越 Java 的限制 (像是無法換掉 final)。聽起來很威,感覺很危險,不確定是否夠穩定。應該不會想試它。
- Mockito 承接 EasyMock 的思維,但是用起來更容易。雖說它也無法換掉 static、private、final 等方法。
我花了一些時間看了 Mockito 範例和作者設計的思路,覺得很有意思。 《behind the times: Mocks and Stubs aren't Spies》 提到在寫測試碼時,替換掉實際互動的元件,有四種不同層級的輔助元件: dummy、stub、spy、mock:
- dummy: 什麼事也不做。
- stub: 依據輸入傳回物件,藉此控制後續的邏輯。(相對來說) 不在意被呼叫的方式,像是何時被呼叫、呼叫了幾次等。
- spy: 用來確認該物件如何被使用。比方說呼叫 cursor 物件的 commit() 前有沒有先呼叫 execute()。
- mock: 同stub + spy,既需要傳回物件供待測方法使用,也在意它如何被呼叫。
寫測試碼常遇到的困擾是:mock 太囉唆了。這篇提供一個小例子對照 Mockito 和 EasyMock 的差異。《should I worry about the unexpected?》 解釋 mock 之所以囉唆,是因為它管太多了,導致加新功能時,常常行為沒錯,卻無法通過舊的測試。使用 spy (Mockito 的主要功能) 就不會有這種困擾。大多情況我們並不在意是否每一個物件都要如預期般執行,只要關鍵的幾個步驟沒錯即可。
之前會排斥使用 mock 的原因為:
- 沒有和真正的物件互動,不夠踏實。
- 寫起來很囉唆。
- 囉唆就算了,稍微改改程式還很容易出錯。
第一點是 trade-off,有時候是不得不做的必要之惡。在看到 spy 的概念後,發覺它少了後兩項缺點。之後需要用到「mock」時,再來用 Mockito 看看。Mockito 另一個好處是,它有提供各種語言的版本,可以學一套語法走天下。