android 單元測試

單元測試的重要的和必要性這里不在強(qiáng)調(diào)斋日,本文介紹幾個(gè)常用的單元測試的框架

JUnit4

JUnit4是一個(gè)java的單元測試框架饰恕,多數(shù)Java的開發(fā)環(huán)境都已經(jīng)集成了JUnit作為單元測試的工具挠羔,android studio默認(rèn)繼承了JUNit4

testImplementation 'junit:junit:4.12'

JUnit4主要是通過注解的方式來識別測試方法,下面介紹幾個(gè)常用的方法以及它的作用:

  • @BeforeClass 在執(zhí)行所有測試方法之前執(zhí)行埋嵌,只執(zhí)行一次破加,對應(yīng)方法必須是靜態(tài)方法
  • @Before 在任意使用@Test注解標(biāo)注方法執(zhí)行之前執(zhí)行
  • @Test 測試方法
  • @After 在任意使用@Test注解標(biāo)注方法執(zhí)行之后執(zhí)行
  • @AfterClass 在執(zhí)行所有測試方法之后執(zhí)行,只執(zhí)行一次莉恼,對應(yīng)方法必須是靜態(tài)方法

了解完以上的信息還沒有完結(jié)拌喉,單元測試還有很重要的一點(diǎn)驗(yàn)證結(jié)果,一般是通過一些assert方法來完成的俐银,JUnit為我們提供的assert方法,多數(shù)都在Assert這個(gè)類里面

  • Assert.assertEquals 驗(yàn)證執(zhí)行結(jié)果與期盼結(jié)果比較端仰,這個(gè)方法的參數(shù)有很多種捶惜,根據(jù)需要使用
  • Assert.assertFalse 驗(yàn)證參數(shù)為false
  • Assert.assertNotNull 驗(yàn)證參數(shù)不為空
  • Assert.assertNotSame 參數(shù)中的兩個(gè)對象不是同一個(gè)對象
  • Assert.assertNull 驗(yàn)證參數(shù)為空
  • Assert.assertSame 參數(shù)中的兩個(gè)對象是同一個(gè)對象
  • Assert.assertThat 實(shí)際情況滿足匹配器給出的條件
  • Assert.assertTrue 驗(yàn)證參數(shù)為true

由于很多地方用到了Assert.assertThat方法,下面列一下啊Matcher常用的方法

  • Matcher.allOf
  • Matcher.anyOf
  • Matcher.both
  • Matcher.containsString
  • Matcher.describedAs
  • Matcher.either
  • Matcher.endsWith
  • Matcher.equalTo
  • Matcher.instanceOf
  • Matcher.is
  • Matcher.hasItem

JUnit單元測試時(shí)是不能使用Android相關(guān)的類的荔烧,下面就來認(rèn)識一下Robolectric框架

Robolectric

Robolectric框架是針對android的測試框架吱七,使用Robolectric框架進(jìn)行單元測試不用依賴真機(jī)或者模擬器,Robolectric支持單元測試范圍從Activity的跳轉(zhuǎn)鹤竭、Activity展示View(包括菜單)和Fragment到View的點(diǎn)擊觸摸以及事件響應(yīng)踊餐,同時(shí)Robolectric也能測試Toast和Dialog。對于需要網(wǎng)絡(luò)請求數(shù)據(jù)的測試臀稚,Robolectric可以模擬網(wǎng)絡(luò)請求的response吝岭。對于一些Robolectric不能測試的對象,比如ConcurrentTask,可以通過自定義Shadow的方式現(xiàn)實(shí)測試窜管。下面將著重介紹Robolectric的常見用法散劫。

引入

testCompile "org.robolectric:robolectric:3.6.1"

官方給出的demo
<pre>
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class MyActivityTest {

@Test
public void clickingButton_shouldChangeResultsViewText() throws Exception {
Activity activity = Robolectric.setupActivity(MyActivity.class);

Button button = (Button) activity.findViewById(R.id.press_me_button);
TextView results = (TextView) activity.findViewById(R.id.results_text_view);

button.performClick();
assertThat(results.getText().toString(), equalTo("Testing Android Rocks!"));

}
}
</pre>

@RunWith(RobolectricGradleTestRunner.class)表示用Robolectric的TestRunner來跑這些test,通過gradle CLI或者Android studio運(yùn)行為單元測試定制的測試運(yùn)行程序幕帆,有一條件必須配置@Config

@RunWith(RobolectricTestRunner.class)提供Android運(yùn)行時(shí)的模擬環(huán)境

Robolectric框架通過shadow類替換對應(yīng)的真實(shí)方法获搏,最終實(shí)現(xiàn)測試脫離底層實(shí)現(xiàn),感興趣的話失乾,可以自行了解

Mock

對于一些依賴關(guān)系復(fù)雜的測試對象常熙,可以采用Mock框架解除依賴,常用的有Mockito,mock創(chuàng)建一個(gè)類的虛假的對象碱茁,用于解耦真實(shí)對象所需要的依賴,Mock得到的對象僅僅是具備測試對象的類型裸卫,并不是真實(shí)的對象,也就是并沒有執(zhí)行過真實(shí)對象的邏輯早芭。

引入

repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:2.+" }

Mock的方法使用

// mock creation
List mockedList = mock(List.class);

// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();

// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();

直接通過mock方法創(chuàng)建虛擬對象彼城,也可以使用注解的方式 @Mock 來創(chuàng)建,通過 verify 方法來檢查相應(yīng)方法是否調(diào)用

stub形式的使用

// you can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);

// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");

// the following prints "first"
System.out.println(mockedList.get(0));

// the following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));

指定關(guān)鍵字 when 返回一個(gè) OngoingStubbing 接口退个,通過其提供的 thenReturn募壕,thenThrow,thenCallRealMethod 及自定義 thenAnswer 來返回相應(yīng)的結(jié)果

Mock中幾個(gè)主要的方法

  • mock()/@Mock: 創(chuàng)建一個(gè)Mock虛擬對象
  • spy()/@Spy: 部分mock语盈,真正的方法會被調(diào)用舱馅,但是仍然需要驗(yàn)證
  • verify(): 檢測方法是否被調(diào)用

通過 times,never刀荒,atLeastOnce代嗤,atLeast,atMost 這些方法缠借,我們可以對一個(gè)方法的調(diào)用次數(shù)做判斷

verify(mockedList, atLeastOnce()).add("three times")

通過doThrow為一個(gè)方法的調(diào)用添加異常干毅,驗(yàn)證代碼對異常的處理

doThrow(new RuntimeException()).when(mockedList).clear();

通過Mockito的inOrder方法驗(yàn)證調(diào)用順序

更多使用方法請參考mock官網(wǎng)

注:final類型、private類型以及靜態(tài)類型的方法不能mock

總結(jié)

JUnit框架主要是用來測試java類的泼返,既能做單元測試也能做集成測試硝逢,如果想要調(diào)用android的方法需要用到Robolectric框架,這兩個(gè)框架可以做的事情很多绅喉,幾乎能滿足你所有的需求渠鸽,但是有的時(shí)候測試需要用到虛擬對象,就需要用到Mock框架了柴罐。

希望這篇文章徽缚,對初次接觸單元測試的你有所幫助

參考文獻(xiàn):

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市革屠,隨后出現(xiàn)的幾起案子凿试,更是在濱河造成了極大的恐慌排宰,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件红省,死亡現(xiàn)場離奇詭異额各,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吧恃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門虾啦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痕寓,你說我怎么就攤上這事傲醉。” “怎么了呻率?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵硬毕,是天一觀的道長。 經(jīng)常有香客問我礼仗,道長吐咳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任元践,我火速辦了婚禮韭脊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘单旁。我一直安慰自己沪羔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布象浑。 她就那樣靜靜地躺著蔫饰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪愉豺。 梳的紋絲不亂的頭發(fā)上篓吁,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音蚪拦,去河邊找鬼越除。 笑死,一個(gè)胖子當(dāng)著我的面吹牛外盯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播翼雀,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼饱苟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了狼渊?” 一聲冷哼從身側(cè)響起箱熬,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤类垦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后城须,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚤认,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年糕伐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了砰琢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡良瞧,死狀恐怖陪汽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情褥蚯,我是刑警寧澤挚冤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站赞庶,受9級特大地震影響训挡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜歧强,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一澜薄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧誊锭,春花似錦表悬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至温治,卻和暖如春饭庞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背熬荆。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工舟山, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卤恳。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓累盗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親突琳。 傳聞我的和親對象是個(gè)殘疾皇子若债,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一.基本介紹 背景: 目前處于高速迭代開發(fā)中的Android項(xiàng)目往往需要除黑盒測試外更加可靠的質(zhì)量保障,這正是單元...
    anmi7閱讀 2,026評論 0 6
  • @Author:彭海波 前言 單元測試(又稱為模塊測試, Unit Testing)是針對程序模塊(軟件設(shè)計(jì)的最小...
    海波筆記閱讀 4,961評論 0 52
  • 什么是單元測試 在計(jì)算機(jī)編程中拆融,單元測試(Unit Testing)又稱為模塊測試, 是針對程序模塊(軟件設(shè)計(jì)的最...
    HelloCsl閱讀 10,953評論 1 46
  • 本文介紹了Android單元測試入門所需了解的內(nèi)容蠢琳,包括JUnit啊终、Mockito和PowerMock的使用,怎樣...
    于衛(wèi)國閱讀 4,576評論 0 5
  • 今天是中秋節(jié)傲须,是合家團(tuán)圓的日子蓝牲。在這一天中,地上的我們享受到了團(tuán)聚在一起彼此祝福的美好泰讽。作為基督徒的我們例衍,在這樣的...
    高橋先生閱讀 175評論 0 0