说说初用 Mock 工具测试碰到的坑
我是一個在校實習生,作為一個程序猿,是個菜鳥中戰斗機!對于測試,只寫過一點點簡單到不能再簡單了的 Junit 單元測試的例子(因為當時這足以應付學校課程的內容與要求)。這幾天在公司里要真槍實彈做測試的時候,就深深體會到了“書到用時方恨少”這句話的真諦了。沒辦法,誰叫我當初不多深入的學點呢。于是,在杜叔杜大神的指導下,開始了菜鳥的初用 Mock 工具,邊學邊用的爬坑之旅。
為什么要用 Mock 工具?
話不多說,我們先直接看看個最簡單的例子:
測試目標:
測試用例:
public class test { @Test public void testEquals(){ ToBeTested t = new ToBeTested(); assertEquals(3,t.add(1,2)); assertEquals(8,t.plus(2,4)); } }這里我們是直接通過 new 來構建了一個 ToBeTested 的實例,因為這個類簡單,而且待測試的方法里也沒有依賴任何外部的對象,就一個簡單的加法或乘法就完事了。但事情總是沒有那么簡單,在做單元測試的時候,我們要測試的方法往往都是需要依賴很多外部的對象,比如網絡通訊,遠程服務之類的,這些外部對象是我么沒法控制的。難道這些外部依賴的對象都需要 new 一個出來嗎 NO! 我們有 Mock! 我們可以用 Mock 工具來模擬這些外部對象,來完成我們的單元測試。還是先來看一個簡單的 Mock 測試的例子吧:
public class test { @Test public void test(){ List<String> list = Mockito.mock(List.class); list.add("coding"); verify(list).add("coding"); } }坑1 : spy
如果要用真實對象(而不是 Mock 出來的虛擬對象)中的真實的方法,則需要 spy 一下!看下面的例子:
我在測試目標代碼中加了一個 compute 函數:
public int compute(int a){ int b = add(a,a); int c = plus(a,a); return b+c; }隨后想當然的寫了個對應的測試用例:
@Test public void testCompute(){ ToBeTested t = new ToBeTested(); assertEquals(8, t.compute(2)); }但聰明的你一看就知道,這不叫單元測試。因為我只是想測試 compute 這個函數是不是正確的,但 compute 卻依賴于 add 和 plus 這兩個函數。如果 add 函數里有錯,也會導致 compute 出錯,可這根本不關 compute 的事啊。所以,測試用例代碼應該是這樣的:
@Test public void testCompute(){ ToBeTested t = spy(new ToBeTested()); when(t.add(2,2)).thenReturn(4); when(t.plus(2, 2)).thenReturn(4); assertEquals(8, t.compute(2)); }注意!這里 new 一個真實對象 t 的時候,需要 spy 一下!(當時年輕不懂事,被這里卡了略久。。)因為這里用到了依賴的方法 add 和 plus。現在對于這個例子,compute 的結果已經不依賴別人了,哪怕 add 方法里,不知是哪個粗心的程序猿寫成了 “return a - b ",這個測試也是通過的,因為這里有?when(t.add(2,2)).thenReturn(4);?這句話,stubbing 了 add 這個方法。這也符合單元測試的概念,我們現在只負責測試 compute 這個函數,才不管 add 或 plus 正確與否呢。
坑2:doReturn
等等,如剛剛所說,compute 已經不依賴 add 的返回結果了,那是不是當我們測試 compute 函數的時候,add 函數是不是就可以完全無法無天的亂來了呢?我們來看看這個:
public int add(int a, int b) { ArrayList<String> list = new ArrayList<String>(); String s = list.get(0); return a+b; }這時,當我們再次執行測試時,就拋異常了:java.lang.IndexOutOfBoundsException?。顯然?list.get(0)?是罪魁禍首!奇怪?不是說 compute 已經不管 add 了嗎? add 里面的代碼有問題又怪我咯?別忘了,這還是 java 語言!所以,when(t.add(2,2)).thenReturn(4);?這語句還是會先去執行一遍 when 里面的函數, add(2,2). 至于返回結果是另外一回事。那么怎么解決這個問題呢?對!用 doReturn 語句!
@Test public void testCompute(){ ToBeTested t = spy(new ToBeTested()); //when(t.add(2,2)).thenReturn(4); doReturn(4).when(t).add(2,2); when(t.plus(2, 2)).thenReturn(4); ; assertEquals(8, t.compute(2)); }現在好了, compute 已經完全不受 add 函數的影響了。add 函數愛怎么瘋就怎么瘋,不會影響 compute 函數的測試結果了,至此, compute 終于可以安靜地完成它的單元測試了。
坑3: PowerMock
現如今比較流行的 Mock 工具如 jMock、EasyMock、Mockito 等都有一個共同的缺點:不能 mock 靜態、final、私有方法等。而 PowerMock 能夠完美的彌補以上三個 Mock 工具的不足。至于怎么做,去 Google 一下一大把的教程與實例,這里就不再多說了。。
坑4,5,6,8,。。。。。
慢慢踩 :)
Last…..
在 coding 實習的時間里,學了很多東西,也還有很多東西等待著我去學習。今后在 coding 這個年輕,充滿激情的團隊里,在杜叔大神的帶領下,希望能夠在爬坑中不斷成長,從菜鳥慢慢變成老鳥,按這樣的節奏發展下去,不久的將來,就能升職加薪,當上總經理,出任 CEO,迎娶白富美,走上人生巔峰,想想都有點小激動呢,嘿嘿。。。
from: https://blog.coding.net/blog/mock-testing-tools
總結
以上是生活随笔為你收集整理的说说初用 Mock 工具测试碰到的坑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java Mocking入门—使用Moc
- 下一篇: 使用Mockito进行Java单元测试