亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

how to learn unit test mock framework

2019-11-11 07:08:24
字體:
來源:轉載
供稿:網友

refer to http://www.strolling.cn/2017/01/how_to_learn_unit_test_mock_framework/

每次使用各種形形色色的單元測試Mock框架都比較暈,因為寫的不夠多,等學會了,又流行了一個新的框架,思考為什么老是記不住以及為什么每次都不能胸有成竹的說自己掌握了,想想估計是因為每次都是現學現用,比較零散,不成體系,所以寫下這個記錄,匯總下到底應該學習,一方面可以幫助在新學一個單元測試mock框架的時候,按照這個順序學,學完之后,按照這個步驟寫CASE;另一方面在使用mockito/powermock時,直接根據場景復制代碼。

必知必會(一)- 搞出“假”對象

既然是單元測試的Mock使用, 第一步要學的是怎么搞出一個假的對象,然后后續工作其實都是圍繞這個假對象做文章。

根據應用場景不同可以劃分為2種方式:

(1)Mock: 制造一個完全的假對象;

根據策略的不同,可以定義不同默認行為的假對象,例如:

所有方法不進行任何真實調用,都統一返回null;

Apple apple= Mockito.mock(Apple.class);

所有方法調用是真實調用

Apple apple= Mockito.mock(Apple.class,Mockito.CALLS_REAL_METHODS);

(2)Spy: 制造一個假對象,但是是基于已有一個真實的對象。

滿足的需求是,大多方法想用真實實例來調用,只想定制實例內部的一些方法。

Apple apple = new Apple();Apple spiedApple= Mockito.spy(apple);

必知必會(二)- 綁定上“假”對象

第一步搞出假對象后,不會就自動使用上了,否則別人不需要用mock的測試怎么測?所以第二步要做的是讓自己的Mock對象使用上,即綁定上被測目標和mocked對象,思考一個類如何使用另外一個類:

1 被測目標自己不創建,而是需要使用者傳遞進去的方式:

(a)作為構造器參數直接傳遞進去; (b)使用Set系方法傳遞進去;

2 被測目標負責創建

本質上創建都是new的過程(PS:除了靜態類), 所以mock掉new,讓new返回要mocked的對象,就搞定所有的事情,但是從被測目標看,不可能都是new,可能這個new離被測目標還是有一定的距離:例如使用工廠類,使用sPRing的@autowire的等等,所以從代碼層次看有以下幾種情況:

(1) Apple apple = new Apple();(2) apple = AppleFactory.getIntance();(3)@Autowiredprivate Apple apple;

(a)針對直接new的方式:讓new出一個對象都返回mock的實例

class AppleTree{private Apple apple= new Apple();}@RunWith(PowerMockRunner.class)@PrepareForTest({AppleTree.class}) //don't miss this statement and pay more attention it is caller for Apple, not Apple.public class TestNewObject { @Testpublic void test() throws Exception {Apple apple= Mockito.mock(Apple.class);PowerMockito.whenNew(Apple.class).withNoArguments().thenReturn(apple);}

(b)針對使用其他類來創建:mock創建方法

一般都是靜態工廠這種情況,如果不是“靜態工廠”,是另外一個實例的普通方法創建的,則需要mock那個實例了。 這里僅考慮一般情況,即面對靜態工廠方法,mockito暫時不支持靜態類的mock,所以需要結合powermock:

@RunWith(PowerMockRunner.class)@PrepareForTest({AppleFactory.class}) //don't miss this statementpublic class TestStaticMethod {@Testpublic void test() throws Exception {Apple apple= Mockito.mock(Apple.class);PowerMockito.mockStatic(AppleFactory.class);PowerMockito.when(AppleFactory.getInstance()).thenReturn(apple);}

(c)還有一種情況是使用框架自動創建的,例如使用Spring的@Autowired 此時可以使用java反射來直接設置進去,但是既然是使用mock工具,也可以使用標準點的方式,例如:

Apple apple= Mockito.mock(Apple.class);Whitebox.setInternalState(testAppleInstance, "apple", apple);

必知必會(三)- Mock對象上做文章-偽造行為

學完前面2步后,就可以開始考慮干活了,既然搞出假的mock對象,不可能不去做一些“假動作”: 匹配上一個方法,然后做出一個行為:

其中匹配包括2種:

粗略匹配:

Mockito.when(mockedApple.getOwner(Mockito.anyString()).thenReturn("tom");

精確匹配:

Mockito.when(mockedApple.getOwner(Mockito.eq("somegstring"))).thenReturn("tom");

行為包括以下三種:

(1) 定義方法非真實調用;

設置其返回值:

Mockito.when(mockedApple.getOwner()).thenReturn("tom");

設置其拋出異常:

Mockito.when(mockedApple.getOwner()).thenThrow(new RuntimeException());

(2)定義方法去進行真實調用:

Mockito.when(mockedApple.getNumbers()).thenCallRealMethod();

(3)自適應變化:

例如設置每次返回的不同可以使用:

when(mockedApple.getOwner()) .thenReturn("one") //第一次行為 .thenCallRealMethod() //第二次行為 .thenThrow(new RuntimeException()); //第三次行為

其他形式的各種高級搞法,不考慮。

必知必會(四)- Mock對象上做文章-驗證行為

不考慮本身case就可以寫出驗證點,有時候需要驗證一些mocked對象上的行為來驗證case是否成功,按照需要驗證的要點來看: (1)驗證調用與否或調用次數

Mockito.verify(mockedApple, Mockito.times(2)).someMethod(Mockito.anyString()); Mockito.verify(mockedApple, Mockito.never()).someMethod(Mockito.anyString());

(2) 驗證調用時間

Mockito.verify(mockedApple, Mockito.timeout(10)).someMethod(Mockito.anyString());

(3)驗證調用參數值

方式1:Matcher-直接驗證參數

簡單校驗:

Mockito.verify(mockedApple, times(2)).someMethod(Mockito.eq("expectedString")); //mockito要求此處不能直接寫"expectedString"

自動義校驗方法:

使用Mockito.argThat+ArgumentMatcher(Matchers.argThat(Matcher matcher) ):

Mockito.verify(mockedApple).someMethod(Mockito.argThat(new ArgumentMatcher<String>(){ @Override public boolean matches(String argument) { return argument.equals("expectedString");}}));

方式2:Captor-捕獲出參數,然后校驗

使用ArgumentCaptor捕獲參數,然后進一步處理的

ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);Mockito.verify(mockedApple).someMethod(argument.capture());String value = argument.getValue();Assert.assertEqual(value, expectedString);

區別: Also, sometimes ArgumentCaptor may be a better fit than custom matcher. For example, if custom argument matcher is not likely to be reused or you just need it to assert on argument values to complete verification of behavior.

(4) 驗證調用順序

主要包括兩種,一種是同一個mock對象的方法調用順序,另外一種是跨mock對象的方法調用順序驗證,分別參考一下兩種示例:

InOrder inOrder = Mockito.inOrder(mockedApple);inOrder.verify(mockedApple).firstMethodCallName();inOrder.verify(mockedApple).secondMethodCallName();InOrder inOrder = Mockito.inOrder(mockedApple,mockedOrange);inOrder.verify(mockedApple).methodCallName();inOrder.verify(mockedOrange).methodCallName();

對于各種驗證,有時候需要reset mock對象,以便處理共享等問題,可以使用Mockito.reset()。

總結:

對于一個新的單元測試框架大體要搞清楚幾件事情:“偽造對象-綁定對象-定制對象動作-驗證” ,核心關鍵是mock/spy it then when customized match one method do something and verify after executed寫具體case的時候,也可以follow四個步驟來搞。另外上面演示的都是基本要點,其他都是各種形式的變種或高級用法,同時每種框架都有自己的特殊要求,必須遵從。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲男人天堂九九视频| 亚洲性线免费观看视频成熟| 亚洲成av人片在线观看香蕉| 成人妇女淫片aaaa视频| 久久网福利资源网站| 国产成人免费91av在线| 色偷偷9999www| 亚洲美女中文字幕| 精品国产户外野外| 国产精品1234| 51精品国产黑色丝袜高跟鞋| 久久久久久伊人| 亚洲精品美女久久久久| 亚洲一区二区久久久久久| 亚洲综合视频1区| 亚洲精品一区二区久| 理论片在线不卡免费观看| 国产精品久久久一区| www.亚洲免费视频| 国产欧美婷婷中文| 亚洲午夜久久久久久久| 黑人极品videos精品欧美裸| 亚洲成人久久久久| 国产日韩欧美中文在线播放| 欲色天天网综合久久| 国产精品视频最多的网站| 91久久精品国产91性色| 国产精品网红直播| 亚洲欧美日韩国产精品| 国外日韩电影在线观看| 国产亚洲视频中文字幕视频| 最近2019好看的中文字幕免费| 久久人人爽人人爽人人片亚洲| 日韩国产一区三区| 亚洲欧美制服中文字幕| 久久久av亚洲男天堂| 日韩欧美精品网址| 亚洲一区二区在线播放| 日本精品视频在线播放| 欧美日韩精品在线视频| 欧美大秀在线观看| 色播久久人人爽人人爽人人片视av| 亚洲国产高潮在线观看| 亚洲经典中文字幕| 欧美日韩国产丝袜另类| 欧美日韩中文字幕在线| 久久久久久久久久久网站| 中文字幕国产精品| 91精品国产自产91精品| 5566日本婷婷色中文字幕97| 日韩av最新在线| 日韩高清电影好看的电视剧电影| 青青草成人在线| 久久亚洲春色中文字幕| 国产成人在线一区二区| 国产在线拍揄自揄视频不卡99| 亚洲精品国产品国语在线| 欧美韩国理论所午夜片917电影| 色婷婷综合久久久久| 欧美黄色片在线观看| 136fldh精品导航福利| 亚洲欧美色图片| 国产精品老牛影院在线观看| 欧美在线欧美在线| 欧美高清在线播放| 亚洲欧美精品一区| 欧美日韩在线一区| 日韩在线视频二区| 日韩av电影免费观看高清| 亚洲成人久久网| 日韩最新av在线| 亚洲福利影片在线| 亚洲精品国产品国语在线| 国产综合福利在线| 久久99久久久久久久噜噜| 亚洲第一网中文字幕| 国产女人精品视频| 欧美日韩国产一中文字不卡| 亚洲欧洲日产国码av系列天堂| 亚洲欧美在线播放| 欧美日韩亚洲91| 日韩精品有码在线观看| 亚洲第一av网| 91精品视频专区| 日韩国产欧美精品在线| 色综合久久中文字幕综合网小说| 国产精品人成电影在线观看| 欧美日韩一区二区三区| 色偷偷91综合久久噜噜| 91人人爽人人爽人人精88v| 亚洲成人黄色网| 日本aⅴ大伊香蕉精品视频| 久久久久中文字幕2018| 中文字幕亚洲情99在线| 亚洲综合成人婷婷小说| 国产精品久久久久久久久久99| 韩国精品美女www爽爽爽视频| 亚洲欧美国产一本综合首页| 欧美性20hd另类| 狠狠躁天天躁日日躁欧美| 97在线精品国自产拍中文| 日本精品免费一区二区三区| 另类少妇人与禽zozz0性伦| 日韩高清电影好看的电视剧电影| 日韩av一区二区在线观看| 国产精品视频在线观看| 亚洲第一网中文字幕| 亚洲人免费视频| 91av中文字幕| 日本免费久久高清视频| 中文字幕亚洲欧美日韩2019| 亚洲精品久久久久国产| 久久九九亚洲综合| 国产亚洲一区精品| 国产精品1区2区在线观看| 亚洲国产女人aaa毛片在线| 国产精品久久久久久久7电影| 综合激情国产一区| 91麻豆国产语对白在线观看| 日韩视频免费看| 亚洲国产精品电影在线观看| 日本韩国欧美精品大片卡二| 国产亚洲美女久久| 亚洲黄色片网站| 中文字幕国产精品久久| 国产精品高潮呻吟久久av无限| 亚洲国产高清高潮精品美女| 久久久久一本一区二区青青蜜月| 亚洲欧美999| 97免费视频在线播放| 欧美日韩国产中文精品字幕自在自线| 国产精品久久久久久久9999| 欧美精品videossex性护士| 久久久999精品免费| 久久亚洲私人国产精品va| 一区三区二区视频| 日韩欧美国产骚| 亚洲欧洲日产国产网站| 中文字幕最新精品| 奇门遁甲1982国语版免费观看高清| 国产精品久久久久久av福利软件| 国产91精品黑色丝袜高跟鞋| 亚洲精品自在久久| 亚洲成人aaa| 欧美精品videofree1080p| 亚洲男人第一网站| 国产精品麻豆va在线播放| 久久最新资源网| 亚洲精品国产品国语在线| 青青a在线精品免费观看| 欧美贵妇videos办公室| 日韩女优人人人人射在线视频| 亚洲国产毛片完整版| 国产精品综合网站| 欧美极品欧美精品欧美视频| 18一19gay欧美视频网站| 欧美大片免费看| 日韩在线视频免费观看高清中文| 国模私拍视频一区| 久久精品免费播放| 久久久久久久电影一区| 欧美午夜视频一区二区| 国产精品美女久久久久久免费| 欧美三级xxx|