国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

歡迎使用CSDN-markdown編輯器

2019-11-11 07:09:12
字體:
供稿:網(wǎng)友

每次使用各種形形色色的單元測試Mock框架都比較暈,因?yàn)閷懙牟粔蚨啵葘W(xué)會了,又流行了一個新的框架,思考為什么老是記不住以及為什么每次都不能胸有成竹的說自己掌握了,想想估計是因?yàn)槊看味际乾F(xiàn)學(xué)現(xiàn)用,比較零散,不成體系,所以寫下這個記錄,匯總下到底應(yīng)該學(xué)習(xí),一方面可以幫助在新學(xué)一個單元測試mock框架的時候,按照這個順序?qū)W,學(xué)完之后,按照這個步驟寫CASE;另一方面在使用mockito/powermock時,直接根據(jù)場景復(fù)制代碼。

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

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

根據(jù)應(yīng)用場景不同可以劃分為2種方式:

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

根據(jù)策略的不同,可以定義不同默認(rèn)行為的假對象,例如:

所有方法不進(jìn)行任何真實(shí)調(diào)用,都統(tǒng)一返回null;

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

所有方法調(diào)用是真實(shí)調(diào)用

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

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

滿足的需求是,大多方法想用真實(shí)實(shí)例來調(diào)用,只想定制實(shí)例內(nèi)部的一些方法。

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

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

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

1 被測目標(biāo)自己不創(chuàng)建,而是需要使用者傳遞進(jìn)去的方式:

(a)作為構(gòu)造器參數(shù)直接傳遞進(jìn)去; (b)使用Set系方法傳遞進(jìn)去;

2 被測目標(biāo)負(fù)責(zé)創(chuàng)建

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

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

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

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)針對使用其他類來創(chuàng)建:mock創(chuàng)建方法

一般都是靜態(tài)工廠這種情況,如果不是“靜態(tài)工廠”,是另外一個實(shí)例的普通方法創(chuàng)建的,則需要mock那個實(shí)例了。 這里僅考慮一般情況,即面對靜態(tài)工廠方法,mockito暫時不支持靜態(tài)類的mock,所以需要結(jié)合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)還有一種情況是使用框架自動創(chuàng)建的,例如使用Spring的@Autowired 此時可以使用java反射來直接設(shè)置進(jìn)去,但是既然是使用mock工具,也可以使用標(biāo)準(zhǔn)點(diǎn)的方式,例如:

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

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

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

其中匹配包括2種:

粗略匹配:

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

精確匹配:

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

行為包括以下三種:

(1) 定義方法非真實(shí)調(diào)用;

設(shè)置其返回值:

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

設(shè)置其拋出異常:

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

(2)定義方法去進(jìn)行真實(shí)調(diào)用:

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

(3)自適應(yīng)變化:

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

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

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

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

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

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

(2) 驗(yàn)證調(diào)用時間

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

(3)驗(yàn)證調(diào)用參數(shù)值

方式1:Matcher-直接驗(yàn)證參數(shù)

簡單校驗(yàn):

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

自動義校驗(yàn)方法:

使用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-捕獲出參數(shù),然后校驗(yàn)

使用ArgumentCaptor捕獲參數(shù),然后進(jìn)一步處理的

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

區(qū)別: 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) 驗(yàn)證調(diào)用順序

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

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();

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

總結(jié):

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


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 龙海市| 赤水市| 云梦县| 江达县| 电白县| 景谷| 汶上县| 扶绥县| 舒城县| 鄂托克前旗| 扶风县| 成安县| 晋宁县| 安顺市| 策勒县| 灵宝市| 秦皇岛市| 宣武区| 繁昌县| 德令哈市| 阿拉善盟| 工布江达县| 芦山县| 正阳县| 乐至县| 肇庆市| 渑池县| 吉林省| 左云县| 黄大仙区| 海伦市| 丰台区| 德州市| 冕宁县| 河津市| 永仁县| 潼南县| 米林县| 饶平县| 宁乡县| 新巴尔虎左旗|