日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android单元测试学习总结

發(fā)布時(shí)間:2024/3/24 Android 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android单元测试学习总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

      • 一、本地單元測(cè)試
        • 1. 創(chuàng)建測(cè)試類
        • 2. Assert類中的常用斷言方法
        • 3. 運(yùn)行測(cè)試類
        • 4. 運(yùn)行單個(gè)測(cè)試方法或多個(gè)測(cè)試類
      • 二、Mockito測(cè)試框架的使用
        • 1. Mock概念的理解
        • 2. Mockito中幾種Mock對(duì)象的方式
        • 3. 驗(yàn)證行為
          • verify(T mock)函數(shù)的使用
          • 使用`when(T methodCall)`函數(shù)
          • 使用`thenAnswer`為回調(diào)做測(cè)試樁
          • 使用`doCallRealMethod()`函數(shù)來調(diào)用某個(gè)方法的真實(shí)實(shí)現(xiàn)方法
          • 使用`doNothing()`函數(shù)是為了設(shè)置void函數(shù)什么也不做
          • 使用`doAnswer()`函數(shù)測(cè)試void函數(shù)的回調(diào)
          • 需要使用doReturn函數(shù)代替thenReturn的情況
          • 使用`doThrow()`函數(shù)來測(cè)試void函數(shù)拋出異常
        • 4. 驗(yàn)證方法的調(diào)用次數(shù)
        • 5. 參數(shù)匹配器 (matchers)
        • 6. 使用InOrder驗(yàn)證執(zhí)行執(zhí)行順序
        • 7. 使用Spy監(jiān)控真實(shí)對(duì)象
        • 8. 使用ArgumentCaptor進(jìn)行參數(shù)捕獲
        • 9. 使用@InjectMocks自動(dòng)注入依賴對(duì)象
      • 三、PowerMockito框架使用
        • 1. 普通Mock的方式
        • 2. Mock方法內(nèi)部new出來的對(duì)象
        • 3. Mock普通對(duì)象的final方法
        • 4. Mock普通類的靜態(tài)方法
        • 5. verify靜態(tài)方法的調(diào)用次數(shù)
        • 6. 使用真實(shí)返回值
        • 7. Mock私有方法
        • 8. Mock普通類的私有變量
        • 9. 對(duì)靜態(tài)void方法進(jìn)行Mock
        • 10. Mock系統(tǒng)的final靜態(tài)類
      • 四、Robolectric測(cè)試框架的使用
      • 五、Espresso測(cè)試框架的使用

Android單元測(cè)試主要分為以下兩種

  • 本地單元測(cè)試(Junit Test), 本地單元測(cè)試是純java代碼的測(cè)試,只運(yùn)行在本地電腦的JVM環(huán)境上,不依賴于Android框架的任何api, 因此執(zhí)行速度快,效率較高,但是無法測(cè)試Android相關(guān)的代碼。
  • 儀器化測(cè)試(Android Test),是針對(duì)Android相關(guān)代碼的測(cè)試,需要運(yùn)行在真機(jī)設(shè)備或模擬器上,運(yùn)行速度較慢,但是可以測(cè)試UI的交互以及對(duì)設(shè)備信息的訪問,得到接近真實(shí)的測(cè)試結(jié)果。

在Android Studio中新建一個(gè)項(xiàng)目的時(shí)候,app的gradle中會(huì)默認(rèn)添加單元測(cè)試的相關(guān)依賴庫(kù):

dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])testImplementation 'junit:junit:4.12'androidTestImplementation 'com.android.support.test:runner:1.0.2'androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }

其中testImplementation添加的依賴就是本地化測(cè)試庫(kù), androidTestImplementation 添加的依賴則是Android環(huán)境下的測(cè)試庫(kù),同時(shí),在項(xiàng)目的工程目錄下也會(huì)默認(rèn)創(chuàng)建好測(cè)試的目錄:

其中app/src/test/下面存放的是Junit本地測(cè)試代碼,app/src/androidTest/下面存放的是Android測(cè)試代碼。

一、本地單元測(cè)試

進(jìn)行本地單元測(cè)試需要先了解一些基本的Junit注解:

注解名稱含義
@Test定義所在方法為單元測(cè)試方法,方法必須是public void
@Before定義所在方法在每個(gè)測(cè)試用例執(zhí)行之前執(zhí)行一次, 用于準(zhǔn)備測(cè)試環(huán)境(如: 初始化類,讀輸入流等),在一個(gè)測(cè)試類中,每個(gè)@Test方法的執(zhí)行都會(huì)觸發(fā)一次調(diào)用
@After定義所在方法在每個(gè)測(cè)試用例執(zhí)行之后執(zhí)行一次,用于清理測(cè)試環(huán)境數(shù)據(jù),在一個(gè)測(cè)試類中,每個(gè)@Test方法的執(zhí)行都會(huì)觸發(fā)一次調(diào)用。
@BeforeClass定義所在方法在測(cè)試類里的所有用例運(yùn)行之前運(yùn)行一次,方法必須是public static void,用于做一些耗時(shí)的初始化工作(如: 連接數(shù)據(jù)庫(kù))
@AfterClass定義所在方法在測(cè)試類里的所有用例運(yùn)行之后運(yùn)行一次,方法必須是public static void,用于清理數(shù)據(jù)(如: 斷開數(shù)據(jù)連接)
@Test (expected = Exception.class)如果該測(cè)試方法沒有拋出Annotation中的Exception類型(子類也可以),則測(cè)試失敗
@Test(timeout=100)如果該測(cè)試方法耗時(shí)超過100毫秒,則測(cè)試失敗,用于性能測(cè)試
@Ignore 或者 @Ignore(“太耗時(shí)”)忽略當(dāng)前測(cè)試方法,一般用于測(cè)試方法還沒有準(zhǔn)備好,或者太耗時(shí)之類的
@FixMethodOrder定義所在的測(cè)試類中的所有測(cè)試方法都按照固定的順序執(zhí)行,可以指定3個(gè)值,分別是DEFAULT、JVM、NAME_ASCENDING(字母順序)
@RunWith指定測(cè)試類的測(cè)試運(yùn)行器

更多可以參考Junit官網(wǎng):https://junit.org/junit4/

1. 創(chuàng)建測(cè)試類

接下來就可以創(chuàng)建測(cè)試類,除了可以手動(dòng)創(chuàng)建測(cè)試類外,可以利用AS快捷鍵:將光標(biāo)選中要?jiǎng)?chuàng)建測(cè)試類的類名上->按下ALT + ENTER->在彈出的彈窗中選擇Create Test

這會(huì)彈出下面的彈窗,或者鼠標(biāo)在類名上右鍵選擇菜單Go to–>Test,也會(huì)彈出下面的彈窗

勾選需要進(jìn)行測(cè)試的方法,會(huì)自動(dòng)生成一個(gè)測(cè)試類:

如果勾選了@Before或@After的話也會(huì)自動(dòng)給你生成對(duì)應(yīng)的測(cè)試方法

接下來編寫測(cè)試方法,首先在要測(cè)試的目標(biāo)類中寫幾個(gè)業(yè)務(wù)方法:

public class SimpleClass {public boolean isTeenager(int age) {if (age < 15) {return true;}return false;}public int add(int a, int b) {return a + b;}public String getNameById(int id) {if (id == 1) {return "小明";} else if (id == 2){return "小紅";}return "";} }

然后,測(cè)試類:

@RunWith(JUnit4.class) public class SimpleClassTest {private SimpleClass simpleClass;@Beforepublic void setUp() throws Exception {simpleClass = new SimpleClass();}@Afterpublic void tearDown() throws Exception {}@Testpublic void isTeenager() {Assert.assertFalse(simpleClass.isTeenager(20));Assert.assertTrue(simpleClass.isTeenager(14));}@Testpublic void add() {Assert.assertEquals(simpleClass.add(3, 2), 5);Assert.assertNotEquals(simpleClass.add(3, 2), 4);}@Testpublic void getNameById() {Assert.assertEquals(simpleClass.getNameById(1), "小明");Assert.assertEquals(simpleClass.getNameById(2), "小紅");Assert.assertEquals(simpleClass.getNameById(10), "");} }

其中setUp()是自動(dòng)生成的添加了@Before注解,這會(huì)在每個(gè)測(cè)試方法執(zhí)行前執(zhí)行,因此在這里創(chuàng)建一個(gè)目標(biāo)對(duì)象,也可以選擇添加@BeforeClass注解但這時(shí)setUp()應(yīng)該改為靜態(tài)的方法。然后在每個(gè)測(cè)試方法中編寫測(cè)試用例,這里使用org.junit.Assert包中的斷言方法,有很多assertXXX方法,可以自己選擇用來判斷目標(biāo)方法的結(jié)果是否滿足預(yù)期。

2. Assert類中的常用斷言方法

方法含義
assertNull(Object object)斷言對(duì)象為空
assertNull(String message, Object object)斷言對(duì)象為空,如果不為空拋出異常攜帶指定的message信息
assertNotNull(Object object)斷言對(duì)象不為空
assertNotNull(Object object)斷言對(duì)象不為空,如果為空拋出異常攜帶指定的message信息
assertSame(Object expected, Object actual)斷言兩個(gè)對(duì)象引用的是同一個(gè)對(duì)象
assertSame(String message, Object expected, Object actual)斷言兩個(gè)對(duì)象引用的是同一個(gè)對(duì)象,否則拋出異常攜帶指定的message信息
assertNotSame(Object expected, Object actual)斷言兩個(gè)對(duì)象引用的不是同一個(gè)對(duì)象
assertNotSame(String message, Object expected, Object actual)斷言兩個(gè)對(duì)象引用的不是同一個(gè)對(duì)象,否則拋出異常攜帶指定的message信息
assertTrue(boolean condition)斷言結(jié)果為true
assertTrue(String message, boolean condition)斷言結(jié)果為true, 為false時(shí)拋出異常攜帶指定的message信息
assertFalse(boolean condition)斷言結(jié)果為false
assertFalse(String message, boolean condition)斷言結(jié)果為false, 為true時(shí)拋出異常攜帶指定的message信息
assertEquals(long expected, long actual)斷言兩個(gè)long 類型 expected 和 actual 的值相等
assertEquals(String message, long expected, long actual)斷言兩個(gè)long 類型 expected 和 actual 的值相等,如不相等則拋異常攜帶指定message信息
assertEquals(Object expected, Object actual)斷言兩個(gè)對(duì)象相等
assertEquals(String message, Object expected, Object actual)斷言兩個(gè)對(duì)象相等,如果不相等則拋出異常攜帶指定的message信息
assertEquals(float expected, float actual, float delta)斷言兩個(gè) float 類型 expect 和 actual 在 delta 偏差值下相等,delta是誤差精度
assertEquals(String message, float expected, float actual, float delta)斷言兩個(gè) float 類型 expect 和 actual 在 delta 偏差值下相等,如果不相等則拋出異常攜帶指定的message信息
assertEquals(double expected, double actual, double delta)斷言兩個(gè) double 類型 expect 和 actual 在 delta 偏差值下相等
assertEquals(String message, double expected,double actual, double delta)斷言兩個(gè) double 類型 expect 和 actual 在 delta 偏差值下相等,如果不相等則拋出異常攜帶指定的message信息
assertArrayEquals(T[] expected, T[] actual)斷言兩個(gè)相同類型的數(shù)組的元素一一對(duì)應(yīng)相等
assertArrayEquals(String message, T[] expected, T[] actual)斷言兩個(gè)相同類型的數(shù)組的元素一一對(duì)應(yīng)相等,如果不相等則拋出異常攜帶指定的message信息
fail()直接讓測(cè)試失敗
fail(String message)直接讓測(cè)試失敗并給出message錯(cuò)誤信息
assertThat(T actual, Matcher<? super T> matcher)斷言actual和matcher規(guī)則匹配
assertThat(String reason, T actual, Matcher<? super T> matcher)斷言actual和matcher規(guī)則匹配,否則拋出異常攜帶指定的reason信息

其中assertEquals的方法,都對(duì)應(yīng)有一個(gè)assertNotEquals方法,這里不列了,assertThat是一個(gè)強(qiáng)大的方法:

Assert.assertThat(1, is(1));Assert.assertThat(0, is(not(1)));Assert.assertThat("hello", startsWith("h"));List<String> items = new ArrayList<>();items.add("aaa");items.add("bbb");Assert.assertThat(items, hasItem("aaa"));

需要靜態(tài)導(dǎo)入org.hamcrest.Matchers類里面的方法,更多匹配方法請(qǐng)參考這個(gè)類。

3. 運(yùn)行測(cè)試類

選中測(cè)試類右鍵Run運(yùn)行,控制面板中就會(huì)顯示測(cè)試結(jié)果:

如果所有的測(cè)試用例都正常返回了預(yù)期的結(jié)果,則面板中左側(cè)每個(gè)測(cè)試方法前面會(huì)帶一個(gè)綠色的對(duì)勾,否則方法前面會(huì)變成紅色感嘆號(hào)并且控制面板會(huì)輸出異常,現(xiàn)在來改一個(gè)業(yè)務(wù)方法試一下:

public boolean isTeenager(int age) {if (age < 15) {return false;}return false;}

這里將age < 15改為輸出false,假設(shè)這是我們?cè)诰幋a的時(shí)候由于疏忽粗心造成的,然后運(yùn)行測(cè)試類:

控制面板會(huì)告訴那一行出錯(cuò)了:

也就是說這里沒有返回預(yù)期的結(jié)果,說明我們編寫的業(yè)務(wù)邏輯是有錯(cuò)誤的,這時(shí)就需要改bug了。

4. 運(yùn)行單個(gè)測(cè)試方法或多個(gè)測(cè)試類

上面是運(yùn)行的整個(gè)測(cè)試類,如果要運(yùn)行測(cè)試類的單個(gè)方法,則鼠標(biāo)只選中某個(gè)要運(yùn)行的測(cè)試方法,然后右鍵選擇Run即可。如果要同時(shí)運(yùn)行多個(gè)測(cè)試類,而如果多個(gè)測(cè)試類在同一個(gè)包下面,則選中多個(gè)測(cè)試類所在的包目錄,然后右鍵選擇Run運(yùn)行。否則可以通過下面的方式指定,創(chuàng)建一個(gè)空的測(cè)試類,然后添加注解:

@RunWith(Suite.class) @Suite.SuiteClasses({SimpleClassTest.class, SimpleClass2Test.class}) public class RunMultiTest { }

運(yùn)行這個(gè)測(cè)試類就可以將指定的測(cè)試類的方法一起運(yùn)行。

二、Mockito測(cè)試框架的使用

前面介紹的只能測(cè)試不涉及Android相關(guān)Api的java代碼用例,如果涉及到Android相關(guān)Api的時(shí)候,就不方便了,這時(shí)如果不依賴第三方庫(kù)的話可能需要使用儀器化測(cè)試跑到Android設(shè)備上去運(yùn)行,于是有一些比較好的第三方的替代框架可以來模擬使用Android的代碼測(cè)試,Mockito就是基于依賴注入實(shí)現(xiàn)的一個(gè)測(cè)試框架。

1. Mock概念的理解

什么是Mock, 這個(gè)單詞的中文意思就是“模仿”或者“虛假”的意思,也就是要模仿一個(gè)對(duì)象,為啥要模仿?
在傳統(tǒng)的JUnit單元測(cè)試中,沒有消除在測(cè)試中對(duì)對(duì)象的依賴,如A對(duì)象依賴B對(duì)象方法,在測(cè)試A對(duì)象的時(shí)候,我們需要構(gòu)造出B對(duì)象,這樣子增加了測(cè)試的難度,或者使得我們對(duì)某些類的測(cè)試無法實(shí)現(xiàn)。這與單元測(cè)試的思路相違背。
還有一個(gè)主要的問題就是本地單元測(cè)試由于是運(yùn)行本地JVM環(huán)境,無法依賴Android的api,只靠純Junit的測(cè)試環(huán)境很難模擬出完整的Android環(huán)境,導(dǎo)致無法測(cè)試Android相關(guān)的代碼,而Mock就能解決這個(gè)問題,通過Mock能夠很輕易的實(shí)現(xiàn)對(duì)象的模擬。

添加依賴:

dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])testImplementation 'org.mockito:mockito-core:2.19.0'.... }

2. Mockito中幾種Mock對(duì)象的方式

使用之前通過靜態(tài)方式導(dǎo)入會(huì)使用更方便:

// 靜態(tài)導(dǎo)入會(huì)使代碼更簡(jiǎn)潔import static org.mockito.Mockito.*;

直接mock一個(gè)對(duì)象:

@Testpublic void testMock() {SimpleClass mockSimple = Mockito.mock(SimpleClass.class);assertNotNull(mockSimple);}

注解方式mock一個(gè)對(duì)象:

@MockSimpleClass simple;@Beforepublic void setUp() {MockitoAnnotations.initMocks(this);}@Testpublic void testMock() {assertNotNull(simple);}

運(yùn)行器方式mock一個(gè)對(duì)象:

@RunWith(MockitoJUnitRunner.class) public class ExampleUnitTest {@MockSimpleClass simple;@Testpublic void testMock() {assertNotNull(simple);} }

MockitoRule方式mock一個(gè)對(duì)象:

public class ExampleUnitTest {@MockSimpleClass simple;@Rule //<--使用@Rulepublic MockitoRule mockitoRule = MockitoJUnit.rule();@Testpublic void testMock() {assertNotNull(simple);} }

3. 驗(yàn)證行為

verify(T mock)函數(shù)的使用

verify(T mock)的作用是驗(yàn)證發(fā)生的某些行為等同于verify(mock, times(1)) 例如:

@Test public void testMock() {//創(chuàng)建mock對(duì)象List mockedList = mock(List.class);//使用mock對(duì)象mockedList.add("one");mockedList.clear();//驗(yàn)證mockedList.add("one")是否被調(diào)用,如果被調(diào)用則當(dāng)前測(cè)試方法通過,否則失敗verify(mockedList).add("one");//驗(yàn)證 mockedList.clear()是否被調(diào)用,如果被調(diào)用則當(dāng)前測(cè)試方法通過,否則失敗verify(mockedList).clear();} @Test public void testMock() {mock.someMethod("some arg");//驗(yàn)證mock.someMethod("some arg")是否被調(diào)用,如果被調(diào)用則測(cè)試方法通過,否則失敗verify(mock).someMethod("some arg");}

也就是說如果把調(diào)用的方法注釋掉,則運(yùn)行testMock()方法就會(huì)失敗。

通過verify關(guān)鍵字,一旦mock對(duì)象被創(chuàng)建了,mock對(duì)象會(huì)記住所有的交互。然后你就可能選擇性的驗(yàn)證你感興趣的交互。

通常需要配合一些測(cè)試方法來驗(yàn)證某些行為,這些方法稱為"打樁方法"(Stub),打樁的意思是針對(duì)mock出來的對(duì)象進(jìn)行一些模擬操作,如設(shè)置模擬的返回值或拋出異常等。

常見的打樁方法:

方法名方法含義
doReturn(Object toBeReturned)提前設(shè)置要返回的值
doThrow(Throwable… toBeThrown)提前設(shè)置要拋出的異常
doAnswer(Answer answer)提前對(duì)結(jié)果進(jìn)行攔截
doCallRealMethod()調(diào)用某一個(gè)方法的真實(shí)實(shí)現(xiàn)
doNothing()設(shè)置void函數(shù)什么也不做
thenReturn(T value)設(shè)置要返回的值
thenThrow(Throwable… throwables)設(shè)置要拋出的異常
thenAnswer(Answer<?> answer)對(duì)結(jié)果進(jìn)行攔截

例如:

@Testpublic void testMock() {// 你可以mock具體的類型,不僅只是接口List mockedList = mock(List.class);// 打測(cè)試樁when(mockedList.get(0)).thenReturn("first");doReturn("aaaa").when(mockedList).get(1);when(mockedList.get(1)).thenThrow(new RuntimeException());doThrow(new RuntimeException()).when(mockedList).clear();// 輸出“first”System.out.println(mockedList.get(0));// 因?yàn)間et(999) 沒有打樁,因此輸出null, 注意模擬環(huán)境下這個(gè)地方是不會(huì)報(bào)IndexOutOfBoundsException異常的System.out.println(mockedList.get(999));// get(1)時(shí)會(huì)拋出異常System.out.println(mockedList.get(1));// clear會(huì)拋出異常mockedList.clear();}

doXXX和thenXXX使用上差不多,一個(gè)是調(diào)用方法之前設(shè)置好返回值,一個(gè)是在調(diào)用方法之后設(shè)置返回值。默認(rèn)情況下,Mock出的對(duì)象的所有非void函數(shù)都有返回值,對(duì)象類型的默認(rèn)返回的是null,例如返回int、boolean、String的函數(shù),默認(rèn)返回值分別是0、false和null。

使用when(T methodCall)函數(shù)

打樁方法需要配合when(T methodCall)函數(shù),意思是使測(cè)試樁方法生效。當(dāng)你想讓這個(gè)mock能調(diào)用特定的方法返回特定的值,那么你就可以使用它。

例如:

when(mock.someMethod()).thenReturn(10);//你可以使用靈活的參數(shù)匹配,例如 when(mock.someMethod(anyString())).thenReturn(10);//設(shè)置拋出的異常when(mock.someMethod("some arg")).thenThrow(new RuntimeException());//你可以對(duì)不同作用的連續(xù)回調(diào)的方法打測(cè)試樁://最后面的測(cè)試樁(例如:返回一個(gè)對(duì)象:"foo")決定了接下來的回調(diào)方法以及它的行為。when(mock.someMethod("some arg")).thenReturn("foo")//第一次調(diào)用someMethod("some arg")會(huì)返回"foo".thenThrow(new RuntimeException());//第二次調(diào)用someMethod("some arg")會(huì)拋異常//可以用以下方式替代比較小版本的連貫測(cè)試樁:when(mock.someMethod("some arg")).thenReturn("one", "two");//和下面的方式效果是一樣的when(mock.someMethod("some arg")).thenReturn("one").thenReturn("two");//比較小版本的連貫測(cè)試樁并且拋出異常:when(mock.someMethod("some arg")).thenThrow(new RuntimeException(), new NullPointerException();
使用thenAnswer為回調(diào)做測(cè)試樁
when(mock.someMethod(anyString())).thenAnswer(new Answer() {Object answer(InvocationOnMock invocation) {Object[] args = invocation.getArguments();Object mock = invocation.getMock();return "called with arguments: " + args;}});// 輸出 : "called with arguments: foo"System.out.println(mock.someMethod("foo"));
使用doCallRealMethod()函數(shù)來調(diào)用某個(gè)方法的真實(shí)實(shí)現(xiàn)方法

注意,在Mock環(huán)境下,所有的對(duì)象都是模擬出來的,而方法的結(jié)果也是需要模擬出來的,如果你沒有為mock出的對(duì)象設(shè)置模擬結(jié)果,則會(huì)返回默認(rèn)值,例如:

public class Person {public String getName() {return "小明";} }@Test public void testPerson() {Person mock = mock(Person.class);//輸出null,除非設(shè)置發(fā)回模擬值when(mock.getName()).thenReturn("xxx");System.out.println(mock.getName()); }

因?yàn)間etName()方法沒有設(shè)置模擬返回值,而getName()返回值是String類型的,因此直接調(diào)用的話會(huì)返回String的默認(rèn)值null,所以上面代碼如果要想輸出getName()方法的真實(shí)返回值的話,需要設(shè)置doCallRealMethod():

@Testpublic void testPerson() {Person mock = mock(Person.class);doCallRealMethod().when(mock).getName();//輸出“小明”System.out.println(mock.getName());}
使用doNothing()函數(shù)是為了設(shè)置void函數(shù)什么也不做

需要注意的是默認(rèn)情況下返回值為void的函數(shù)在mocks中是什么也不做的但是,也會(huì)有一些特殊情況。如:

測(cè)試樁連續(xù)調(diào)用一個(gè)void函數(shù)時(shí):

doNothing().doThrow(new RuntimeException()).when(mock).someVoidMethod();//does nothing the first time:mock.someVoidMethod();//throws RuntimeException the next time:mock.someVoidMethod();

監(jiān)控真實(shí)的對(duì)象并且你想讓void函數(shù)什么也不做:

List list = new LinkedList(); List spy = spy(list);//let's make clear() do nothing doNothing().when(spy).clear();spy.add("one");//clear() does nothing, so the list still contains "one" spy.clear();
使用doAnswer()函數(shù)測(cè)試void函數(shù)的回調(diào)

當(dāng)你想要測(cè)試一個(gè)無返回值的函數(shù)時(shí),可以使用一個(gè)含有泛型類Answer參數(shù)的doAnswer()函數(shù)做回調(diào)測(cè)試。假設(shè)你有一個(gè)void方法有多個(gè)回調(diào)參數(shù),當(dāng)你想指定執(zhí)行某個(gè)回調(diào)時(shí),使用thenAnswer很難實(shí)現(xiàn)了,如果使用doAnswer()將非常簡(jiǎn)單,示例代碼如下:

MyCallback callback = mock(MyCallback.class); Mockito.doAnswer(new Answer() {@Overridepublic Object answer(InvocationOnMock invocationOnMock) throws Throwable {//獲取第一個(gè)參數(shù)MyCallback call = invocation.getArgument(0);//指定回調(diào)執(zhí)行操作call.onSuccess();return null;}}).when(mockedObject.requset(callback));doAnswer(new Answer() {@Overridepublic Object answer(InvocationOnMock invocation) throws Throwable {System.out.println("onSuccess answer");return null;}}).when(callback).onSuccess();mockedObject.requset(callback)
需要使用doReturn函數(shù)代替thenReturn的情況

如當(dāng)監(jiān)控真實(shí)的對(duì)象并且調(diào)用真實(shí)的函數(shù)帶來的影響時(shí)

List list = new LinkedList(); List spy = spy(list);//不可能完成的:真實(shí)方法被調(diào)用的時(shí)候list仍是空的,所以spy.get(0)會(huì)拋出IndexOutOfBoundsException()異常 when(spy.get(0)).thenReturn("foo");//這時(shí)你應(yīng)該使用doReturn()函數(shù) doReturn("foo").when(spy).get(0);
使用doThrow()函數(shù)來測(cè)試void函數(shù)拋出異常
SimpleClass mock = mock(SimpleClass.class); doThrow(new RuntimeException()).when(mock).someVoidMethod(); mock.someVoidMethod();

總之使用doThrow(), doAnswer(), doNothing(), doReturn() and doCallRealMethod() 這些函數(shù)時(shí)可以在適當(dāng)?shù)那闆r下調(diào)用when()來解決一些問題., 如當(dāng)你需要下面這些功能時(shí)這是必須的:

  • 測(cè)試void函數(shù)
  • 在受監(jiān)控的對(duì)象上測(cè)試函數(shù)
  • 不只一次的測(cè)試同一個(gè)函數(shù),在測(cè)試過程中改變mock對(duì)象的行為

4. 驗(yàn)證方法的調(diào)用次數(shù)

需要配合使用一些方法

方法含義
times(int wantedNumberOfInvocations)驗(yàn)證調(diào)用方法的次數(shù)
never()驗(yàn)證交互沒有發(fā)生,相當(dāng)于times(0)
only()驗(yàn)證方法只被調(diào)用一次,相當(dāng)于times(1)
atLeast(int minNumberOfInvocations)至少進(jìn)行n次驗(yàn)證
atMost(int maxNumberOfInvocations)至多進(jìn)行n次驗(yàn)證
after(long millis)在給定的時(shí)間后進(jìn)行驗(yàn)證
timeout(long millis)驗(yàn)證方法執(zhí)行是否超時(shí)
description(String description)驗(yàn)證失敗時(shí)輸出的內(nèi)容
verifyZeroInteractions驗(yàn)證mock對(duì)象沒有交互

例如:

mock.someMethod("some arg"); mock.someMethod("some arg"); //驗(yàn)證mock.someMethod("some arg")被連續(xù)調(diào)用兩次,即如果沒有調(diào)用兩次則驗(yàn)證失敗 verify(mock, times(2)).someMethod("some arg"); //注意,下面三種是等價(jià)的,都是驗(yàn)證someMethod()被只調(diào)用一次 verify(mock).someMethod("some arg"); verify(mock, times(1)).someMethod("some arg"); verify(mock, only()).someMethod("some arg"); mPerson.getAge(); mPerson.getAge(); //驗(yàn)證至少調(diào)用2次 verify(mPerson, atLeast(2)).getAge(); //驗(yàn)證至多調(diào)用2次 verify(mPerson, atMost(2)).getAge(); //下面兩種等價(jià),驗(yàn)證調(diào)用次數(shù)為0 verify(mPerson, never()).getAge(); verify(mPerson, times(0)).getAge(); mPerson.getAge(); mPerson.getAge(); long current = System.currentTimeMillis(); System.out.println(current ); //延時(shí)1s后驗(yàn)證mPerson.getAge()是否被執(zhí)行了2次 verify(mPerson, after(1000).times(2)).getAge(); System.out.println(System.currentTimeMillis() - current); mPerson.getAge();mPerson.getAge();//驗(yàn)證方法在100ms超時(shí)前被調(diào)用2次verify(mPerson, timeout(100).times(2)).getAge(); @Testpublic void testVerifyZeroInteractions() {Person person = mock(Person.class);person.eat("a");//由于person對(duì)象發(fā)生了交互,所以這里驗(yàn)證失敗,把上面的調(diào)用注釋掉這里就會(huì)驗(yàn)證成功verifyZeroInteractions(person);//可以驗(yàn)證多個(gè)對(duì)象沒有交互//verifyZeroInteractions(person,person2 );} @Testpublic void testVerifyZeroInteractions() {Person person = mock(Person.class);person.eat("a");verify(person).eat("a");//注意,這將會(huì)無法到達(dá)驗(yàn)證目的,不能跟verify()混用verifyZeroInteractions(person,person2 );}

5. 參數(shù)匹配器 (matchers)

Mockito以自然的java風(fēng)格來驗(yàn)證參數(shù)值: 使用equals()函數(shù)。有時(shí),當(dāng)需要額外的靈活性時(shí)你可能需要使用參數(shù)匹配器,也就是argument matchers :

// 使用內(nèi)置的anyInt()參數(shù)匹配器when(mockedList.get(anyInt())).thenReturn("element");// 使用自定義的參數(shù)匹配器( 在isValid()函數(shù)中返回你自己的匹配器實(shí)現(xiàn) )when(mockedList.contains(argThat(isValid()))).thenReturn("element");// 輸出elementSystem.out.println(mockedList.get(999));// 你也可以驗(yàn)證參數(shù)匹配器verify(mockedList).get(anyInt());

常用的參數(shù)匹配器:

方法名含義
anyObject()匹配任何對(duì)象
any(Class type)與anyObject()一樣
any()與anyObject()一樣
anyBoolean()匹配任何boolean和非空Boolean
anyByte()匹配任何byte和非空Byte
anyCollection()匹配任何非空Collection
anyDouble()匹配任何double和非空Double
anyFloat()匹配任何float和非空Float
anyInt()匹配任何int和非空Integer
anyList()匹配任何非空List
anyLong()匹配任何long和非空Long
anyMap()匹配任何非空Map
anyString()匹配任何非空String
contains(String substring)參數(shù)包含給定的substring字符串
argThat(ArgumentMatcher matcher)創(chuàng)建自定義的參數(shù)匹配模式
eq(T value)匹配參數(shù)等于某個(gè)值

一些示例代碼:

@Testpublic void testPersonAny(){when(mPerson.eat(any(String.class))).thenReturn("米飯");//或:when(mPerson.eat(anyString())).thenReturn("米飯");//輸出米飯System.out.println(mPerson.eat("面條"));}@Testpublic void testPersonContains(){when(mPerson.eat(contains("面"))).thenReturn("面條");//輸出面條System.out.println(mPerson.eat("面"));}@Testpublic void testPersonArgThat(){//自定義輸入字符長(zhǎng)度為偶數(shù)時(shí),輸出面條。when(mPerson.eat(argThat(new ArgumentMatcher<String>() {@Overridepublic boolean matches(String argument) {return argument.length() % 2 == 0;}}))).thenReturn("面條");//輸出面條System.out.println(mPerson.eat("1234"));}

需要注意的是,如果你打算使用參數(shù)匹配器,那么所有參數(shù)都必須由匹配器提供。例如:

verify(mock).someMethod(anyInt(), anyString(), eq("third argument")); // 上述代碼是正確的,因?yàn)閑q()也是一個(gè)參數(shù)匹配器verify(mock).someMethod(anyInt(), anyString(), "third argument"); // 上述代碼是錯(cuò)誤的, 因?yàn)樗袇?shù)必須由匹配器提供,而參數(shù)"third argument"并非由參數(shù)匹配器提供,因此會(huì)拋出異常

像anyObject(), eq()這樣的匹配器函數(shù)不會(huì)返回匹配器。它們會(huì)在內(nèi)部將匹配器記錄到一個(gè)棧當(dāng)中,并且返回一個(gè)假的值,通常為null。

6. 使用InOrder驗(yàn)證執(zhí)行執(zhí)行順序

驗(yàn)證執(zhí)行執(zhí)行順序主要使用InOrder函數(shù)
如,驗(yàn)證mock一個(gè)對(duì)象的函數(shù)執(zhí)行順序:

@Testpublic void testInorder() {List<String> singleMock = mock(List.class);singleMock.add("小明");singleMock.add("小紅");// 為該mock對(duì)象創(chuàng)建一個(gè)inOrder對(duì)象InOrder inOrder = inOrder(singleMock);// 驗(yàn)證add函數(shù)首先執(zhí)行的是add("小明"),然后才是add("小紅"),否則測(cè)試失敗inOrder.verify(singleMock).add("小明");inOrder.verify(singleMock).add("小紅");}

驗(yàn)證多個(gè)mock對(duì)象的函數(shù)執(zhí)行順序:

@Testpublic void testInorderMulti() {List<String> firstMock = mock(List.class);List<String> secondMock = mock(List.class);firstMock.add("小明");secondMock.add("小紅");// 為這兩個(gè)Mock對(duì)象創(chuàng)建inOrder對(duì)象InOrder inOrder = inOrder(firstMock, secondMock);// 驗(yàn)證它們的執(zhí)行順序inOrder.verify(firstMock).add("小明");inOrder.verify(secondMock).add("小紅");}

驗(yàn)證執(zhí)行順序是非常靈活的,你不需要一個(gè)一個(gè)的驗(yàn)證所有交互,只需要驗(yàn)證你感興趣的對(duì)象即可。 你可以選擇單個(gè)mock對(duì)象和多個(gè)mock對(duì)象混合著來,也可以僅通過那些需要驗(yàn)證順序的mock對(duì)象來創(chuàng)建InOrder對(duì)象。

7. 使用Spy監(jiān)控真實(shí)對(duì)象

監(jiān)控真實(shí)對(duì)象使用spy()函數(shù)生成,或者也可以像@Mock那樣使用@Spy注解來生成一個(gè)監(jiān)控對(duì)象, 當(dāng)你你為真實(shí)對(duì)象創(chuàng)建一個(gè)監(jiān)控(spy)對(duì)象后,在你使用這個(gè)spy對(duì)象時(shí)真實(shí)的對(duì)象也會(huì)也調(diào)用,除非它的函數(shù)被stub了。盡量少使用spy對(duì)象,使用時(shí)也需要小心形式。

@Testpublic void testSpy() {List<String> list = new ArrayList<>();List<String> spy = spy(list);// 你可以選擇為某些函數(shù)打樁when(spy.size()).thenReturn(100);// 調(diào)用真實(shí)對(duì)象的函數(shù)spy.add("one");spy.add("two");// 輸出第一個(gè)元素"one"System.out.println(spy.get(0));// 因?yàn)閟ize()函數(shù)被打樁了,因此這里返回的是100System.out.println(spy.size());// 驗(yàn)證交互verify(spy).add("one");verify(spy).add("two");}

使用@Spy生成監(jiān)控對(duì)象:

@SpyPerson mSpyPerson;@Testpublic void testSpyPerson() {//將會(huì)輸出Person 類中g(shù)etName()的真實(shí)實(shí)現(xiàn),而不是nullSystem.out.println(mSpyPerson.getName());}

理解監(jiān)控真實(shí)對(duì)象非常重要!有時(shí),在監(jiān)控對(duì)象上使用when(Object)來進(jìn)行打樁是不可能或者不切實(shí)際的。因此,當(dāng)使用監(jiān)控對(duì)象時(shí)請(qǐng)考慮doReturn|Answer|Throw()函數(shù)族來進(jìn)行打樁。例如:

List list = new LinkedList(); List spy = spy(list);// 不可能實(shí)現(xiàn) : 因?yàn)楫?dāng)調(diào)用spy.get(0)時(shí)會(huì)調(diào)用真實(shí)對(duì)象的get(0)函數(shù), // 此時(shí)會(huì)發(fā)生IndexOutOfBoundsException異常,因?yàn)檎鎸?shí)List對(duì)象是空的when(spy.get(0)).thenReturn("foo");// 你需要使用doReturn()來打樁 doReturn("foo").when(spy).get(0);

8. 使用ArgumentCaptor進(jìn)行參數(shù)捕獲

參數(shù)捕獲主要為了下一步的斷言做準(zhǔn)備,示例代碼:

@Testpublic void argumentCaptorTest() {List<Object> mock = mock(List.class);mock.add("John");//構(gòu)建要捕獲的參數(shù)類型,這里是StringArgumentCaptor argument = ArgumentCaptor.forClass(String.class);//在verify方法的參數(shù)中調(diào)用argument.capture()方法來捕獲輸入的參數(shù)verify(mock).add(argument.capture());//驗(yàn)證“John”參數(shù)捕獲assertEquals("John", argument.getValue());} @Testpublic void argumentCaptorTest2() {List<Object> mock = mock(List.class);mock.add("Brian");mock.add("Jim");ArgumentCaptor argument = ArgumentCaptor.forClass(String.class);verify(mock, times(2)).add(argument.capture());//如果又多次參數(shù)調(diào)用,argument.getValue()捕獲到的是最后一次調(diào)用的參數(shù)assertEquals("Jim", argument.getValue());//如果要獲取所有的參數(shù)值可以調(diào)用argument.getAllValues()assertArrayEquals(new Object[]{"Brian","Jim"}, argument.getAllValues().toArray());}

9. 使用@InjectMocks自動(dòng)注入依賴對(duì)象

有時(shí)我們要測(cè)試的對(duì)象內(nèi)部需要依賴另一個(gè)對(duì)象,例如:

public class User {private Address address;public void setAddress(Address address) {this.address = address;}public String getAddress() {return address.getDetail();} } public class Address {public String getDetail() {return "detail Address";} }

User類內(nèi)部需要依賴Address類,當(dāng)我們測(cè)試的時(shí)候需要mock出這兩個(gè)對(duì)象,然后將Address對(duì)象傳入到User當(dāng)中,這樣如果依賴的對(duì)象多了的話就相當(dāng)麻煩,Mockito 提供了可以不用去手動(dòng)注入對(duì)象的方法,首先使用@InjectMocks注解需要被注入的對(duì)象,如User,然后需要被依賴注入的對(duì)象使用@Mock或@Spy注解,之后Mockito 會(huì)自動(dòng)完成注入過程,例如:

@InjectMocksUser mTestUser;@MockAddress mAddress;@Testpublic void argumentInjectMock() {when(mAddress.getDetail()).thenReturn("浙江杭州");System.out.println(mTestUser.getAddress());}

這樣就不用關(guān)心為User 設(shè)置Address ,只要為User需要依賴的類添加注解就可以了,然后直接將重點(diǎn)放到測(cè)試方法的編寫上。

或者使用@Spy監(jiān)控真實(shí)對(duì)象注入也可以:

@InjectMocksUser mTestUser;@SpyAddress mAddress;@Testpublic void argumentInjectMock() {// when(mAddress.getDetail()).thenReturn("浙江杭州");System.out.println(mTestUser.getAddress());}

其他:

連續(xù)調(diào)用的另一種更簡(jiǎn)短的版本:

// 第一次調(diào)用時(shí)返回"one",第二次返回"two",第三次返回"three"when(mock.someMethod("some arg")).thenReturn("one", "two", "three");

參考:Mockito 中文文檔

三、PowerMockito框架使用

Mockito框架基本滿足需求但是有一些局限性,如對(duì)static、final、private等方法不能mock,PowerMockito就可以解決這些問題,PowerMockito是一個(gè)擴(kuò)展了其它如EasyMock等mock框架的、功能更加強(qiáng)大的框架。PowerMock使用一個(gè)自定義類加載器和字節(jié)碼操作來模擬靜態(tài)方法,構(gòu)造函數(shù),final類和方法,私有方法,去除靜態(tài)初始化器等等。

添加依賴:

testImplementation 'org.powermock:powermock-module-junit4:2.0.2'testImplementation 'org.powermock:powermock-module-junit4-rule:2.0.2'testImplementation 'org.powermock:powermock-api-mockito2:2.0.2'testImplementation 'org.powermock:powermock-classloading-xstream:2.0.2'

1. 普通Mock的方式

目標(biāo)類:

public class CommonExample {public boolean callArgumentInstance(File file) {return file.exists();} }

測(cè)試類:

public class CommonExamplePowerMockTest {@Testpublic void testCallArgumentInstance() {File file = PowerMockito.mock(File.class);CommonExample commonExample = new CommonExample();PowerMockito.when(file.exists()).thenReturn(true);Assert.assertTrue(commonExample.callArgumentInstance(file));}}

普通Mock方式是外部傳遞Mock參數(shù),基本上和單獨(dú)使用Mockito是一樣的,使用純Mockito的api也可以完成這個(gè)測(cè)試。

2. Mock方法內(nèi)部new出來的對(duì)象

public class CommonExample {public boolean callArgumentInstance(String path) {File file = new File(path);return file.exists();} } @RunWith(PowerMockRunner.class) @PrepareForTest(CommonExample.class) public class CommonExamplePowerMockTest {@Testpublic void callCallArgumentInstance2() throws Exception {File file = PowerMockito.mock(File.class);CommonExample commonExample = new CommonExample();PowerMockito.whenNew(File.class).withArguments("aaa").thenReturn(file);PowerMockito.when(file.exists()).thenReturn(true);Assert.assertTrue(commonExample.callArgumentInstance("aaa"));} }

跟前面有一點(diǎn)區(qū)別的就是,這里要測(cè)試的方法內(nèi)部創(chuàng)建了File對(duì)象,這時(shí)需要通過PowerMockito.whenNew(File.class).withArguments("aaa").thenReturn(file)方法模擬創(chuàng)建File的操作,當(dāng)File類以aaa的參數(shù)創(chuàng)建的時(shí)候返回已經(jīng)mock出來的file對(duì)象。同時(shí)這時(shí)需要在測(cè)試類上添加注解@RunWith(PowerMockRunner.class)和@PrepareForTest(CommonExample.class),注意是在類上面添加,不是在方法上,一開始在方法上添加時(shí)提示找不到測(cè)試方法,@PrepareForTest()括號(hào)里面指定的是要測(cè)試的目標(biāo)類。

3. Mock普通對(duì)象的final方法

public class CommonExample {public boolean callFinalMethod(DependencyClass dependency) {return dependency.isValidate();} }public class DependencyClass {public final boolean isValidate() {// do somethingreturn false;} } @RunWith(PowerMockRunner.class) @PrepareForTest({CommonExample.class, DependencyClass.class}) public class CommonExamplePowerMockTest {@Testpublic void callFinalMethod() {DependencyClass dependency = PowerMockito.mock(DependencyClass.class);CommonExample commonExample = new CommonExample();PowerMockito.when(dependency.isValidate()).thenReturn(true);Assert.assertTrue(commonExample.callFinalMethod(dependency));} }

同樣這里mock出來需要依賴的類的對(duì)象,然后傳遞給調(diào)用方法,這里同樣需要添加@RunWith和@PrepareForTest,@PrepareForTest可以指定多個(gè)目標(biāo)類,但是這里如果你只需要測(cè)試final的話,只添加DependencyClass.class一個(gè)就可以了。

4. Mock普通類的靜態(tài)方法

public final class Utils {public static String getUUId() {return UUID.randomUUID().toString();} }public class CommonExample {public String printUUID() {return Utils.getUUId();} } @RunWith(PowerMockRunner.class) @PrepareForTest(Utils.class) public class StaticUnitTest {@Beforepublic void setUp() throws Exception {PowerMockito.mockStatic(Utils.class);}@Testpublic void getUUId() {PowerMockito.when(Utils.getUUId()).thenReturn("FAKE UUID");CommonExample commonExample = new CommonExample();assertThat(commonExample.printUUID(), is("FAKE UUID"));} }

同樣需要指定@RunWith和@PrepareForTest,@PrepareForTest中指定靜態(tài)方法所在的類,測(cè)試靜態(tài)方法之前需要調(diào)用PowerMockito.mockStatic()方法來mock靜態(tài)類,然后就通過when().thenReturn()方法指定靜態(tài)方法的模擬返回值即可。

5. verify靜態(tài)方法的調(diào)用次數(shù)

@Testpublic void testVerify() {PowerMockito.when(Utils.getUUId()).thenReturn("FAKE UUID");CommonExample commonExample = new CommonExample();System.out.println(commonExample.printUUID());PowerMockito.verifyStatic(Utils.class);Utils.getUUId();}

靜態(tài)方法通過PowerMockito.verifyStatic(Class c)進(jìn)行驗(yàn)證,不過這里跟Mocktio有一點(diǎn)區(qū)別的是需要在這個(gè)方法的后面再調(diào)用一次靜態(tài)方法,否則不行。這里PowerMockito.verifyStatic(Utils.class)其實(shí)等同于PowerMockito.verifyStatic(Utils.class, times(1)),如果想驗(yàn)證超過一次的,那么:

@Testpublic void testVerify() {PowerMockito.when(Utils.getUUId()).thenReturn("FAKE UUID");CommonExample commonExample = new CommonExample();System.out.println(commonExample.printUUID());System.out.println(commonExample.printUUID());PowerMockito.verifyStatic(Utils.class, Mockito.times(2));Utils.getUUId();}

這時(shí)PowerMockito.verifyStatic()第一個(gè)參數(shù)指定靜態(tài)方法類的Class,第二個(gè)參數(shù)接收一個(gè)VerificationMode類型的參數(shù),因此傳遞Mockito中的任何驗(yàn)證方法次數(shù)的函數(shù)都可以,Mockito中的驗(yàn)證函數(shù)會(huì)返回的是一個(gè)VerificationMode類型。同樣在PowerMockito.verifyStatic方法后面要調(diào)用一次要驗(yàn)證的靜態(tài)方法,總感覺這里很奇怪。。。

6. 使用真實(shí)返回值

如果在測(cè)試的過程中又遇到不需要mock出來的靜態(tài)方法的模擬返回值,而是需要真實(shí)的返回值,怎么辦呢,其實(shí)跟Mockito一樣,PowerMockito同樣提供thenCallRealMethod或者doCallRealMethod方法:

@Testpublic void testRealCall() throws Exception {PowerMockito.when(Utils.getUUId()).thenReturn("FAKE UUID");//...PowerMockito.when(Utils.getUUId()).thenCallRealMethod();//與下面等價(jià)//PowerMockito.doCallRealMethod().when(Utils.class, "getUUId");System.out.println(Utils.getUUId());}

或者直接使用spy監(jiān)控真實(shí)對(duì)象也可以:

@Testpublic void testRealCall() {PowerMockito.spy(Utils.class);System.out.println(Utils.getUUId());}

7. Mock私有方法

public class CommonExample {public boolean callPrivateMethod() {return isExist();}private boolean isExist() {return false;}} @RunWith(PowerMockRunner.class) @PrepareForTest(CommonExample.class) public class PrivateUnitTest {@Testpublic void testCallPrivateMethod() throws Exception {CommonExample commonExample = PowerMockito.mock(CommonExample.class);PowerMockito.when(commonExample.callPrivateMethod()).thenCallRealMethod();PowerMockito.when(commonExample, "isExist").thenReturn(true);Assert.assertTrue(commonExample.callPrivateMethod());} }

在使用上跟純Mockito的沒有太大區(qū)別,只不過Mock私有方法是通過下面的api實(shí)現(xiàn)的:

PowerMockito.when(Object instance, String methodName, Object... arguments)

在PowerMockito中when函數(shù)與Mockito相比,最大的變化就是多了一些傳遞String類型的methodName的重載方法,這樣在使用上幾乎無所不能了。

8. Mock普通類的私有變量

public class CommonExample {private static final int STATE_NOT_READY = 0;private static final int STATE_READY = 1;private int mState = STATE_NOT_READY;public boolean doSomethingIfStateReady() {if (mState == STATE_READY) {// DO some thingreturn true;} else {return false;}}} @Testpublic void testDoSomethingIfStateReady() throws Exception {CommonExample sample = new CommonExample();Whitebox.setInternalState(sample, "mState", 1);assertThat(sample.doSomethingIfStateReady(), is(true));}

通過Whitebox.setInternalState來改變私有成員變量,這種情況下不需要指定@RunWith和@PrepareForTest。

9. 對(duì)靜態(tài)void方法進(jìn)行Mock

public class CommonExample {public static void doSomething(String a) {System.out.println("doSomething"+a);} } @RunWith(PowerMockRunner.class) @PrepareForTest({CommonExample.class}) public class StaticUnitTest {@Testpublic void testStaticVoid() throws Exception {PowerMockito.mockStatic(CommonExample.class);PowerMockito.doNothing().when(CommonExample.class, "doSomething", Mockito.any());CommonExample.doSomething("aaa");} }

默認(rèn)情況下通過PowerMockito.mockStatic的靜態(tài)類的void的方法是什么也不做的,但是可以顯示的執(zhí)行doNothing, 上面的代碼將doNothing那行注釋掉也是什么也不做的。那如果想做一些事而不是doNothing呢,跟Mockito一樣,采用doAnswer:

@Testpublic void testStaticVoid() throws Exception {PowerMockito.mockStatic(CommonExample.class);PowerMockito.doAnswer(new Answer<Object>() {@Overridepublic Object answer(InvocationOnMock invocation) throws Throwable {System.out.println(invocation.getArguments()[0]);return null;}}).when(CommonExample.class, "doSomething", Mockito.any());CommonExample.doSomething("aaa");}

10. Mock系統(tǒng)的final靜態(tài)類

public class CommonExample {public int callSystemStaticMethod(int a, int b) {return Math.max(a, a+b);} } @RunWith(PowerMockRunner.class) @PrepareForTest(CommonExample.class) public class StaticUnitTest {@Testpublic void callSystemStaticMethod() {CommonExample commonExample = new CommonExample();PowerMockito.mockStatic(Math.class);PowerMockito.when(Math.max(anyInt(), anyInt())).thenReturn(100);Assert.assertEquals(100, commonExample.callSystemStaticMethod(10, -5));} }

@PrepareForTest中添加調(diào)用系統(tǒng)類所在的類,這里需要注意的是如果你使用PowerMockito來mock系統(tǒng)靜態(tài)final類,則gradle依賴中不能再添加單純Mockito的依賴庫(kù),否則這里將不能mock成功,會(huì)提示Mockito can not mock/spy final class, 因?yàn)镻owerMockito本身已經(jīng)有對(duì)Mockito的依賴庫(kù)支持了,所以只依賴PowerMockito就可以了。除了系統(tǒng)靜態(tài)final類的情況,其他的情況下PowerMockito和Mockito可以同時(shí)依賴(我測(cè)試是沒有問題的)。另外單純的Mockito新版本中也支持對(duì) final 類 final 方法的 Mock,但是需要添加配置文件并不友好。

四、Robolectric測(cè)試框架的使用

由于Robolectric部分的內(nèi)容比較長(zhǎng),所以單獨(dú)放了一篇文章中:Android單元測(cè)試框架Robolectric的學(xué)習(xí)使用

五、Espresso測(cè)試框架的使用

Espresso是用于Android儀器化測(cè)試的測(cè)試框架,是谷歌官方主推的一個(gè)測(cè)試庫(kù)。由于Espresso部分的內(nèi)容也比較長(zhǎng),所以單獨(dú)放了一篇文章中:Espresso測(cè)試框架的使用

總結(jié)

以上是生活随笔為你收集整理的Android单元测试学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

最近中文字幕在线播放 | 国产精品h在线观看 | 亚洲精品在线免费 | www.久草视频 | 西西大胆免费视频 | 91爱爱网址| 二区三区精品 | 国产一区二区网址 | av成人动漫 | 蜜臀av性久久久久av蜜臀妖精 | 久久九九影院 | 亚洲精选视频在线 | 精品一区精品二区 | 麻豆视频一区 | 日日操天天操狠狠操 | 日韩高清毛片 | 麻豆视频在线观看免费 | 亚洲天堂精品 | 亚洲视频,欧洲视频 | 99视频国产精品 | 三级av小说| 成人午夜电影久久影院 | 国产精品va | 成人黄色电影在线 | 91亚色在线观看 | 久久精品精品电影网 | 欧美性色19p| 亚洲精品美女久久17c | 国产99久久久精品视频 | 成人午夜精品福利免费 | 超碰99人人 | 免费av看片 | 四虎影视欧美 | 2020天天干夜夜爽 | 国产黄影院色大全免费 | 91视频91蝌蚪 | 亚洲欧洲成人 | 日日干天天插 | 亚洲欧美激情精品一区二区 | 激情六月婷婷久久 | 国产福利av| 国产人在线成免费视频 | 日韩欧美视频在线 | www.com久久久| 日韩丝袜视频 | 久久久综合香蕉尹人综合网 | 久久在线精品 | 国产亚洲视频在线 | 国产69久久久欧美一级 | 337p西西人体大胆瓣开下部 | 日韩欧美精品在线 | 久久69精品久久久久久久电影好 | 婷婷精品进入 | 中文字幕人成一区 | 免费观看mv大片高清 | 日韩黄色一级电影 | 丁香婷婷综合五月 | 日韩在线免费不卡 | 国产高清av免费在线观看 | 欧美日韩在线观看不卡 | 国产麻豆成人传媒免费观看 | 国产精品毛片久久久久久久 | 久久国产精品久久久久 | 中文字幕国内精品 | 免费在线观看黄色网 | 国产一区二区三区高清播放 | 免费在线观看视频a | 91麻豆精品国产91 | 97成人在线免费视频 | 麻豆精品视频在线观看免费 | 欧美无极色 | 欧美福利精品 | 亚洲欧美激情精品一区二区 | 开心激情久久 | 久久久www成人免费毛片 | 久久久久亚洲国产精品 | 国产精品嫩草影院123 | 一区二区三区在线免费 | 92精品国产成人观看免费 | 亚洲一级免费电影 | www.久久91 | 久久乱码卡一卡2卡三卡四 五月婷婷久 | 国产成人一区二区三区在线观看 | 特级毛片aaa | 久色免费视频 | 精品在线一区二区三区 | 成人网在线免费视频 | 午夜在线免费视频 | 久久久精品 一区二区三区 国产99视频在线观看 | 狠狠综合网 | 久久久久国产成人精品亚洲午夜 | 久草热久草视频 | 97国产在线播放 | 日本中文字幕网 | 国产视频九色蝌蚪 | 91亚洲国产成人 | av综合在线观看 | a成人v在线 | 91网站在线视频 | 亚洲精品综合一二三区在线观看 | 五月天天色| 人人爽人人舔 | 精品国产一区二区三区四区vr | 国产精品97| 91精品久| 精品久久99| 国产成人免费观看 | 日韩黄色大片在线观看 | 亚洲精品资源在线观看 | 日韩电影中文,亚洲精品乱码 | 17婷婷久久www| 亚洲日本中文字幕在线观看 | 日韩在线精品视频 | 最新日韩中文字幕 | 黄色a级片在线观看 | 久久精品一二三区 | 日日噜噜噜噜夜夜爽亚洲精品 | 91视频高清完整版 | 久久久精品久久 | 国产一级在线观看 | 免费福利在线 | 日韩高清一 | 亚洲日本欧美在线 | 国产精品久久久久久久久毛片 | 日韩在线播放视频 | 永久黄网站色视频免费观看w | 91久久爱热色涩涩 | 欧美日韩一区二区三区不卡 | 丁香六月婷婷开心婷婷网 | 成人午夜电影免费在线观看 | 久草在线观看视频免费 | 久久免费精品国产 | 欧美一区二区在线 | 国产 日韩 在线 亚洲 字幕 中文 | 乱男乱女www7788 | 国产精品尤物 | 911免费视频 | 成人黄在线 | 亚洲一级在线观看 | 国内精品久久久精品电影院 | 最新国产精品视频 | 亚洲午夜大片 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 韩国在线视频一区 | 黄色a视频| 久久天天躁夜夜躁狠狠躁2022 | 一级一片免费看 | 久久国产免费 | 四虎精品成人免费网站 | 欧美做受xxx | 国产精品久久久影视 | 亚洲精品91天天久久人人 | 日韩,中文字幕 | 日本中文字幕在线看 | 狠狠躁日日躁夜夜躁av | 国内精品99| 西西www4444大胆在线 | 国产成人精品一区二区三区 | 国产精品99久久久久久小说 | 久久久在线观看 | 久久久久黄色 | 深夜国产福利 | 香蕉影院在线播放 | 久久蜜臀av | 精品福利视频在线观看 | 色婷丁香| 国产午夜精品久久 | 国产最新视频在线观看 | 国内揄拍国内精品 | 黄色国产精品 | 欧美性天天 | 精品久久久免费视频 | 色婷婷综合久久久久中文字幕1 | 91天天操| 天天爱天天操天天干 | 又污又黄的网站 | 欧美日韩亚洲精品在线 | 日韩免| av大全在线观看 | 国产亚洲视频中文字幕视频 | 亚洲欧美精品在线 | 国产免费国产 | 欧美日本三级 | 国产99久久久久久免费看 | 99免费在线 | 亚洲天堂网在线视频观看 | 婷婷成人亚洲综合国产xv88 | 中文字幕一区二区三区精华液 | 麻豆视频免费看 | 亚洲免费专区 | 久久96国产精品久久99软件 | 久久久久女人精品毛片九一 | 亚洲 中文 欧美 日韩vr 在线 | 国产人成看黄久久久久久久久 | 免费又黄又爽的视频 | av免费在线播放 | 日韩毛片在线播放 | 一区二区毛片 | 久久久久久免费毛片精品 | 国产免费影院 | 五月婷婷丁香综合 | a在线播放 | 免费在线h| 久久久久网址 | 色福利网站 | 日韩一级黄色av | 成人a在线 | 国产精品麻豆一区二区三区 | 国产精品免费在线 | 亚洲理论视频 | 久草线| 成人久久久久久久久 | 亚洲精品久久激情国产片 | www.久久婷婷 | 91视频三区| 在线观看亚洲国产 | 国内精品久久久久久久影视麻豆 | 99色人| 黄色av一区二区三区 | 国产精品一区二区在线播放 | 国产成人在线网站 | 日韩在线免费播放 | 成人av直播| 在线色吧| 欧美污污网站 | aaa日本高清在线播放免费观看 | 日韩精品字幕 | 久久成人麻豆午夜电影 | 天天操天天干天天干 | 一区二区三区久久 | 日韩午夜电影 | 久久黄色网| 欧美亚洲成人xxx | 中文字幕一区二区三 | 国产亚洲视频在线免费观看 | 欧美乱码精品一区 | 国产精品久久嫩一区二区免费 | 亚洲综合射 | 日韩毛片在线播放 | 免费在线色视频 | 91香蕉视频 mp4 | 免费日韩电影 | 免费在线观看一级片 | 天天射天天色天天干 | 久久午夜电影网 | 精品国产观看 | 国产在线久久久 | 最近更新中文字幕 | 精品国偷自产国产一区 | 午夜性盈盈 | 国内精品久久久久久久 | 91福利视频免费观看 | 成人免费观看视频大全 | 久久久久久久久久久电影 | 欧美精品一二三 | 伊人天天色 | 国产成人一区二区精品非洲 | 欧美精品日韩 | 国产精品高潮呻吟久久av无 | 亚洲 欧美 综合 在线 精品 | 91污视频在线 | 人人射人人射 | 久久久精品99 | 日韩在观看线 | 日韩 精品 一区 国产 麻豆 | 99成人在线视频 | 欧美激情第十页 | 人人揉人人揉人人揉人人揉97 | 亚洲国产小视频在线观看 | 在线观看视频99 | 欧美国产一区在线 | 国产成人久久av免费高清密臂 | 国产成人久久精品77777 | 久久综合国产伦精品免费 | 91成年视频 | 久久久噜噜噜久久久 | 中文字幕在线观看一区二区 | 天天干夜夜擦 | 麻豆视频免费入口 | 中文字幕亚洲高清 | 最近中文字幕在线中文高清版 | 亚洲日本一区二区在线 | 久久a热6 | 久久国产精品影片 | a级国产乱理论片在线观看 伊人宗合网 | 久久精品视 | 麻豆播放 | 男女拍拍免费视频 | av网址最新 | 国产韩国日本高清视频 | 中文字幕在线免费观看 | 精品国产电影一区二区 | 欧美午夜理伦三级在线观看 | 婷婷av在线| 中文av资源站 | 日日干 天天干 | www.天天干.com | 日韩免费看视频 | a在线视频v视频 | 午夜精品视频一区 | 国产美女久久 | 麻豆视频在线免费 | 午夜精品一区二区三区在线 | 成人免费视频网站在线观看 | 精品国偷自产在线 | 超碰在线97免费 | 97日日碰人人模人人澡分享吧 | 美女av免费 | 91日韩精品| 国产精品女人网站 | 中文字幕一区二区三区四区视频 | 亚洲乱码在线观看 | 18女毛片 | av三级在线播放 | 免费福利视频导航 | 国产香蕉久久精品综合网 | 久久久久综合网 | 国产精品一区二区三区观看 | 91在线91拍拍在线91 | 国产中文字幕三区 | 激情婷婷亚洲 | 在线香蕉视频 | 在线看片中文字幕 | 91系列在线 | 亚洲网站在线看 | 国产精品人人做人人爽人人添 | 日韩电影在线视频 | 亚洲1区在线 | 久草在线视频首页 | 精品视频9999 | 久久99久久99精品 | 日本少妇高清做爰视频 | www91在线| av资源免费观看 | 中文字幕在线色 | 天天伊人狠狠 | www.精选视频.com | 午夜精品一区二区三区视频免费看 | 免费亚洲黄色 | 国产一区二区在线观看视频 | 开心激情五月婷婷 | 久久久色| 国产一区播放 | 91九色在线视频 | 婷婷在线视频 | 中文在线www | 91av蜜桃| 亚洲高清在线观看视频 | 亚洲精品乱码白浆高清久久久久久 | 亚洲成人家庭影院 | 开心婷婷色 | 最近中文字幕在线播放 | 干 操 插 | 亚洲黄色三级 | 久久99精品久久久久久 | 久草资源免费 | 干 操 插| 免费高清无人区完整版 | 97日日碰人人模人人澡分享吧 | 在线观看亚洲国产 | 欧美a级片免费看 | 久久免费电影网 | 日韩高清一区在线 | 天堂av网在线 | 探花视频免费在线观看 | 亚洲成av人片在线观看 | 国产精品一区二区你懂的 | 国产精品乱码久久久久久1区2区 | 探花视频在线观看免费版 | 美女网站视频免费都是黄 | 日韩一级黄色大片 | 视频一区在线播放 | av一级久久| 久久9999久久免费精品国产 | 午夜色性片 | 国产在线精品区 | 五月天激情综合 | 国产中文字幕视频在线观看 | 天天爽天天爽天天爽 | 国产精品一区二区在线观看 | 日韩精品一区二区在线 | 国产精品久久久久久久久毛片 | 一级片免费观看 | 色综合久久88色综合天天免费 | 五月天精品视频 | 日日干日日 | 日韩精品一区二区三区视频播放 | 国产在线精品观看 | 一区二区在线影院 | av成人免费网站 | 亚洲精品国产精品99久久 | 国产亚洲成av人片在线观看桃 | 久久福利小视频 | 久久看视频| 精品一区av | 玖玖爱免费视频 | 一区二区三区在线电影 | 亚洲黄色免费在线看 | 免费在线观看成人av | 99视频精品视频高清免费 | 麻豆91视频| 欧美日韩免费一区二区三区 | 天天综合网久久综合网 | 91传媒在线| 丁香五月亚洲综合在线 | 亚洲天堂精品视频 | 在线观看国产一区二区 | 国产一区久久久 | 日韩专区av | 国产91在 | 在线91观看 | 国产午夜亚洲精品 | 黄色三级在线观看 | 国产精品久久久免费看 | 成年美女黄网站色大片免费看 | 久草视频播放 | 久久另类小说 | 在线观看视频一区二区三区 | 国产免费久久 | 91成人免费在线视频 | 四虎影视精品成人 | 播五月综合 | av超碰在线观看 | 成人精品在线 | 天天综合成人网 | 日韩欧美国产视频 | 干天天 | 国产精品一区电影 | 日韩精品一区二区免费 | 超碰99在线 | 日本99干网 | 久久久久久久久久久高潮一区二区 | 午夜视频一区二区 | 少妇高潮冒白浆 | 亚洲国产资源 | 久久综合九色综合久99 | 精品福利在线视频 | 日韩免费三级 | 在线电影a | 免费在线观看日韩视频 | 激情欧美丁香 | 国产精品美女久久久久久久 | 国产不卡视频在线 | 日韩免费高清在线观看 | 天天·日日日干 | 日精品在线观看 | 日韩精品欧美精品 | 免费视频久久久 | 国产传媒中文字幕 | 色视频网站在线 | 亚洲精品tv久久久久久久久久 | 精品亚洲午夜久久久久91 | 激情欧美在线观看 | av在线精品 | 久久不卡免费视频 | 免费精品国产va自在自线 | 久久综合狠狠综合 | 久操中文字幕在线观看 | 9999精品视频 | 日韩成人精品一区二区三区 | 91av电影网 | 97色婷婷人人爽人人 | 免费看黄色91 | 亚洲国产日韩欧美 | 国产高清专区 | 超碰97网站 | 国产精品激情 | 欧美成人播放 | 成年人在线免费视频观看 | 高清不卡毛片 | 日韩激情在线视频 | 高清免费在线视频 | 在线观看完整版免费 | 国产精品久久网 | 午夜久久久久久久久久影院 | 成 人 黄 色 片 在线播放 | 亚洲精品短视频 | 精品免费 | 国产午夜免费视频 | 色999在线| 国产午夜三级一区二区三桃花影视 | 精品国产一区二区三区在线 | 亚洲成人精品在线观看 | 日韩高清国产精品 | 一区 在线 影院 | 国产精品中文字幕av | 黄色精品视频 | 午夜在线免费视频 | av色网站 | 91在线永久| 精品在线一区二区三区 | 久久99最新地址 | 午夜在线日韩 | 国产精品原创av片国产免费 | 中午字幕在线观看 | 精品 一区 在线 | 久久精品国产免费 | 国产黄色理论片 | 91桃色在线播放 | 久久综合九色 | 99精品国产高清在线观看 | 99久热在线精品视频观看 | 91高清一区 | 99产精品成人啪免费网站 | 在线黄色国产电影 | 深爱婷婷| 91亚洲精品视频 | 九九日九九操 | 婷婷久久亚洲 | 在线黄频 | 狠狠操欧美 | 免费亚洲精品视频 | 日韩av五月天 | 成人久久久久久久久 | 91香蕉视频黄色 | 国产高清黄色 | 欧美激情精品久久久久 | 国产精品视频久久 | 天天做天天干 | 成人av免费播放 | 伊人天堂av | 欧美国产日韩一区二区 | 欧美成年性 | 中文字幕在线观看不卡 | 亚洲天堂网站视频 | 日日操夜夜操狠狠操 | 色视频在线观看 | 国产精品手机在线播放 | 91porny九色在线播放 | 亚洲涩综合 | 午夜精品福利在线 | 欧美一级免费在线 | 婷婷丁香花五月天 | 久久99精品久久久久久久久久久久 | 中文字幕日韩在线播放 | 免费在线中文字幕 | 欧美久久久 | 欧美亚洲一级片 | 日韩极品视频在线观看 | 青草视频在线看 | 国产精品免费小视频 | 99久久精品无码一区二区毛片 | 国产美女网站在线观看 | 久久综合久久综合这里只有精品 | 日本久久久久久久久久久 | 欧美久久精品 | 久久久久99999 | 天天射日 | 成人av午夜 | 欧美性久久久久久 | 亚洲欧美激情插 | 视频在线亚洲 | 亚洲男人天堂a | 在线国产激情视频 | 久久久久久久久亚洲精品 | 久久国产精品免费看 | 欧美精品小视频 | 国产精品永久久久久久久久久 | 国产精品久久久久久久免费 | 99久久99视频只有精品 | 日日干网址| 亚洲欧洲中文日韩久久av乱码 | 久久精品91视频 | 成人xxxx| 色香蕉在线视频 | 绯色av一区| 在线网址你懂得 | 91网页版免费观看 | 五月婷婷毛片 | 欧美老少交 | 日本动漫做毛片一区二区 | 国产精品 中文在线 | www.亚洲黄色 | 国产亚洲字幕 | 久久免费视频这里只有精品 | 成人黄色短片 | 国产五月婷 | 国产高清免费 | 国产在线高清视频 | 综合网欧美 | 激情视频一区二区三区 | 国产 欧美 日韩 | 激情小说网站亚洲综合网 | 免费看色的网站 | 欧美国产日韩在线观看 | 欧美激情精品久久 | 午夜久久电影网 | 国产 欧美 日韩 | 色香com. | 亚洲综合视频在线播放 | 免费福利在线视频 | 婷婷在线视频 | 手机看片国产 | 亚洲精品美女久久 | 国产在线精品区 | 另类五月激情 | 最近日本中文字幕 | 在线观看中文字幕一区 | 国产成人精品a | 丁香五婷 | 免费在线激情电影 | 人人超碰免费 | 激情视频一区 | 婷婷色在线播放 | 国产一级精品绿帽视频 | 嫩模bbw搡bbbb搡bbbb | a级片在线播放 | 国产精品久久久一区二区 | 日韩国产精品久久 | av资源在线观看 | 久久99国产综合精品免费 | 黄色免费看片网站 | 九九热精品视频在线播放 | 黄色片视频在线观看 | 91在线视频播放 | 久久久久久伊人 | 亚洲做受高潮欧美裸体 | 特级黄色片免费看 | 日韩精品中文字幕在线 | 日韩免费在线视频观看 | 国产精品成人一区 | 免费精品国产 | 九九免费精品 | 欧美激情综合色 | 99激情网 | 综合色天天 | 免费看高清毛片 | 亚洲第二色 | 午夜久久福利视频 | 国产精品区二区三区日本 | 不卡的av电影 | 亚洲欧美日韩国产一区二区 | 午夜精品久久久久久久久久 | 日韩一区二区三区在线看 | 久久久999免费视频 日韩网站在线 | 综合五月婷婷 | 91成人网在线播放 | 五月婷婷中文网 | www视频在线观看 | 日韩精品中文字幕av | av黄色大片| 国产主播大尺度精品福利免费 | 久久草av| 91在线视频播放 | 欧美天天综合 | 男女激情网址 | 日本黄色免费电影网站 | 在线看av的网址 | 久久影视一区二区 | 精品国产aⅴ一区二区三区 在线直播av | 午夜影院一级片 | av福利在线播放 | 欧美福利片在线观看 | 91免费高清视频 | 日韩在线观看网站 | 丁香久久综合 | 高清视频一区 | 综合视频在线 | 中文字幕在线影院 | 国产精品第二十页 | 日韩性xxxx | 色狠狠一区二区 | 日韩免费三级 | 在线观看成人国产 | 中文字幕亚洲欧美日韩 | 久久视频精品在线观看 | 久久在现| 精品一区久久 | 久久精品视频3 | 欧美日韩国产一区二 | 超碰在线97国产 | 最新高清无码专区 | 日韩av免费观看网站 | 久久久国产在线视频 | 超碰成人网 | 色综合久久久久网 | 欧美一区免费观看 | 超碰个人在线 | 99看视频在线观看 | 国产手机在线观看视频 | 亚洲香蕉在线观看 | 超碰在线最新 | 亚洲精品自拍 | 草久在线| 久草成人在线 | 久久成人18免费网站 | 91日韩精品一区 | 日av免费| 91cn国产在线| 九九热在线视频免费观看 | 91在线小视频 | 天天爱综合| 91在线免费播放视频 | 国产一级大片在线观看 | 99综合久久 | 国产麻豆剧果冻传媒视频播放量 | 色偷偷88欧美精品久久久 | 涩涩网站在线播放 | 在线观看蜜桃视频 | 午夜精品久久久久久99热明星 | 91精品一区二区三区蜜臀 | 成人aaa毛片 | 超碰av在线播放 | 亚洲专区免费观看 | 91成人免费在线视频 | 免费一区在线 | 成人动漫一区二区 | 主播av在线 | 欧美日韩国产一区二区在线观看 | 国产精品成人一区二区 | 亚洲在线 | 久久综合久色欧美综合狠狠 | 天天干夜夜干 | 国产日韩欧美在线影视 | japanesefreesexvideo高潮| 91天天操 | 午夜国产一区二区三区四区 | 黄色片网站免费 | 91精品视频免费看 | 色在线免费观看 | 中文字幕在线观看免费高清完整版 | 狠狠狠狠狠操 | 国产精品18久久久久白浆 | 黄色一级在线视频 | 国产一级片观看 | 热re99久久精品国产99热 | 国产精品不卡在线观看 | 九九九热精品免费视频观看网站 | 91av视频网站 | 在线观看亚洲视频 | 国产真实在线 | 亚洲日本欧美在线 | 超碰日韩 | 一区二区三区免费网站 | 国产精品剧情在线亚洲 | 最近中文字幕大全中文字幕免费 | 九九九视频在线 | 国产亚洲精品精品精品 | 亚洲网站在线 | 久久高清片| 在线看成人 | 波多野结衣电影一区二区 | 中文字幕亚洲欧美 | 精品国产乱码 | 香蕉久久久久久av成人 | 黄色毛片视频免费观看中文 | 91精品在线免费观看 | 婷婷精品国产欧美精品亚洲人人爽 | 9ⅰ精品久久久久久久久中文字幕 | 国产粉嫩在线观看 | 麻豆久久久 | 成人a视频片观看免费 | 亚洲一级电影视频 | 99精品热视频 | 国产精品久久久久久久久久三级 | 超碰在线91| 国产蜜臀av | 五月婷婷中文网 | 精品在线免费视频 | 日日夜夜精品免费观看 | 波多野结衣视频网址 | 涩涩伊人 | 成人黄色小说网 | 四虎国产精品免费观看视频优播 | 91传媒在线 | 色综合久久88色综合天天人守婷 | 免费久久99精品国产婷婷六月 | 在线观看国产成人av片 | 国产成人av综合色 | 在线看片a| 国产精品a久久久久 | 国产精品免费观看久久 | 国产一二三四在线观看视频 | 天天爽夜夜爽人人爽曰av | 国产精品免费在线播放 | 亚洲精品视频网址 | 黄色毛片一级 | 国产伦精品一区二区三区高清 | www.五月激情.com| 一区二区三区手机在线观看 | 色综合久久88 | 最新真实国产在线视频 | a黄色片在线观看 | 片网站| 国产精品久久久久久久久久免费看 | 久久99久久99精品免观看软件 | 久久一区二区三区超碰国产精品 | 色综合久久五月 | 成人午夜毛片 | 日韩精品无 | 久久久.com | 黄免费在线观看 | 国产精品99久久久久久武松影视 | 久久精品国产亚洲a | 一级a毛片高清视频 | 日本精品一区二区三区在线播放视频 | 日韩一级片观看 | 亚洲 成人 欧美 | 爱色av.com | 国产一级片在线播放 | 在线 影视 一区 | av黄色免费网站 | 97超碰在线资源 | 亚洲人天堂 | 国产亚洲精品久久久久久无几年桃 | 麻豆视频大全 | 日韩精品一区二区三区免费观看 | 午夜18视频在线观看 | 久久激情视频 久久 | 少妇搡bbb| 久久久久久久久影院 | 国产网红在线 | 国产女人18毛片水真多18精品 | av成人免费在线 | 1024久久| 国产精品久久 | 国产精品美女免费 | 色99中文字幕 | 91喷水 | a亚洲视频| 狠狠操欧美 | 免费观看十分钟 | 在线看日韩 | 日韩精品久久久久久久电影竹菊 | 亚洲香蕉在线观看 | 婷婷网五月天 | 日韩欧美高清视频在线观看 | 免费欧美精品 | 天天操天天摸天天干 | 91av资源在线 | 免费成人av网站 | 亚洲精品国产精品久久99 | 一区二区 久久 | 91免费高清观看 | av电影在线播放 | 丁香激情视频 | 免费不卡中文字幕视频 | 亚洲 欧美变态 另类 综合 | 韩国av不卡 | 亚洲久在线 | 99综合视频| 亚洲精品午夜视频 | 人人看黄色 | 亚洲日本在线视频观看 | 狠狠操操操 | 蜜桃传媒一区二区 | 婷婷综合成人 | 91在线在线观看 | 国产精品一区二区三区电影 | 久久久久久久久电影 | 久久精品国产一区二区电影 | 丝袜美腿一区 | 国产精品国产三级国产不产一地 | 亚洲国产免费看 | 91九色国产 | 色狠狠综合天天综合综合 | 亚洲精品永久免费视频 | 成人黄色电影在线播放 | 一区二区三区精品在线视频 | 17videosex性欧美 | 欧美一级片在线免费观看 | 丁香婷婷激情国产高清秒播 | 狠狠干网 | 亚洲国产中文字幕在线观看 | 中文字幕一区在线观看视频 | 中文字幕在线观看第一页 | 91视频麻豆视频 | 亚洲精品国产拍在线 | 在线观看av小说 | 国产视频一区二区在线播放 | 欧美一级爽 | 日韩精品专区 | 日韩免费久久 | 免费视频久久久久 | 日韩免费在线视频观看 | 一区二区三区四区影院 | 黄色av播放| www.狠狠操.com | 国产99久久精品一区二区永久免费 | 亚洲开心激情 | 91在线www | 久久96国产精品久久99软件 | 日韩欧美69 | 玖玖在线播放 | 亚洲狠狠 | 国内精品久久久久久久影视简单 | 超碰97人| 亚洲va欧美va国产va黑人 | 久久综合五月天 | 亚洲精品日韩av | 精品久久一区二区 | 免费久久久 | 在线三级av| 久久性生活片 | 久久手机免费观看 | 久久亚洲热 | 超碰在线观看av | a一片一级| 欧美日韩性生活 | 欧美一级激情 | 国产视频综合在线 | 91日韩在线播放 | 日本在线观看一区二区三区 | 国内免费久久久久久久久久久 | av官网| 蜜桃视频精品 | 97热视频 | 亚洲精品影视 | 国产在线精品一区二区 | 99色人 | 国产精品美乳一区二区免费 | 国产精品视频免费 | 手机在线黄色网址 | av解说在线观看 | 人人干人人爽 | 91中文字幕网 | 国产精品久久网 | 久久综合欧美精品亚洲一区 | 日本精品一区二区在线观看 | 精品美女久久久久 | 久久精品韩国 | 亚洲视频免费在线观看 | 精品久久久久国产免费第一页 | 国产女人免费看a级丨片 | 97国产超碰| 麻豆传媒一区二区 | 精品美女久久久久久免费 | 亚洲黄色免费网站 | 国产视频一区精品 | 综合久久久久久久 | 综合天天久久 | 97色视频在线| 婷婷丁香激情五月 | 免费网站在线观看人 | 亚洲精品乱码久久久久久蜜桃欧美 | 激情丁香久久 | 亚洲成人精品久久久 | 中文高清av | 人人澡人人爽欧一区 | www视频免费在线观看 | 免费在线观看不卡av | 天天色天天射天天干 | 欧美一级欧美一级 | 手机av片 | 亚洲女同ⅹxx女同tv | 国产乱对白刺激视频不卡 | 精品国偷自产国产一区 | 国产精品video爽爽爽爽 | 日韩精品中文字幕一区二区 | 国产精品一区二区av | 日韩精品在线一区 | 久久久精品欧美 | 日韩区视频 | 色综合天天在线 | 蜜臀av夜夜澡人人爽人人桃色 | 国产在线成人 | 婷婷亚洲综合五月天小说 | av免费在线播放 | 久久成人午夜视频 | 99热这里只有精品国产首页 | 人人超在线公开视频 | 婷婷视频在线播放 | 在线观看中文字幕dvd播放 | 午夜精品久久久99热福利 | 日韩精品1区2区 | 91视频-88av | 91精品91| 日韩理论在线播放 | 国产午夜精品一区 | 丝袜美腿在线播放 | 97视频人人免费看 | 日本在线观看中文字幕无线观看 | 久久视频国产精品免费视频在线 | 亚洲国内精品在线 | 欧美一级性生活视频 | 亚洲精品理论片 | 国产精品久久片 | 欧美久久久影院 | 久久人人爽人人片 | 国产91免费在线观看 | 99久久久久国产精品免费 | 黄色a级片在线观看 | 日韩a免费 | 精品中文字幕在线播放 | 亚洲黄色三级 | 黄色午夜网站 | 国产99久久九九精品 | 久久久久久久久影视 | 欧美永久视频 | 国产成人精品综合久久久 | 人人cao | 色狠狠干 | 日韩性xxx| www.福利 | 久久午夜电影院 | 国产精品久久久免费看 | 国产精品免费视频久久久 | www久久|