日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android mock测试资源,Android 单元测试 --Mock 及 Mockito

發布時間:2024/9/19 Android 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android mock测试资源,Android 单元测试 --Mock 及 Mockito 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

以前我在

Mock 概念

所謂的 Mock 就是創建一個類的虛假的對象,在測試環境中,用來替換掉真實的對象,主要提供兩大功能:

驗證這個對象的某些方法的調用情況,調用了多少次,參數是什么等等

指定這個對象的某些方法的行為,返回特定的值,或者是執行特定的動作

要使用 Mock,一般需要用到 Mock 框架,這篇文章我們使用 Mockito 這個框架,這個是Java界使用最廣泛的一個mock框架。

在 Gradle 添加 Mockito 依賴1

2復制代碼repositories { jcenter() }

dependencies { testCompile "org.mockito:mockito-core:1.+" }復制代碼

如何使用?

我們首先看一下官方的例子://mock creation List

mockedList = mock(List.class);

//using mock object - it does not throw any "unexpected interaction" exception

mockedList.add("one");

// selective, explicit, highly readable verification

verify(mockedList).add("one");復制代碼

一般使用 Mockito 需要執行下面三步:

模擬并替換測試代碼中外部依賴。

執行測試代碼

驗證測試代碼是否被正確的執行

創建 Mock 對象的方式:

mock(toMockObject.class)

注解的方式 @Mock,注意要利用注解, 首先要告訴 Mockito 框架, 可以@Rule public MockitoRule mockitoRule = MockitoJUnit.rule); 或者它的實現MockitoAnnotations.initMocks(target);

誤區一

上面的例子我們進行修改 ==> 為不同于上面的地方,如下://mock creation List

mock(List.class);

List list = new ArrayList<>();

//using mock object - it does not throw any "unexpected interaction" exception

list.add("one");

// selective, explicit, highly readable verification

verify(list).add("one");復制代碼

運行發現如下錯誤:

org.mockito.exceptions.misusing.NotAMockException:

Argument passed to verify() is of type ArrayList and is not a mock!

Make sure you place the parenthesis correctly!

See the examples of correct verifications:

verify(mock).someMethod();

verify(mock, times(10)).someMethod();

verify(mock, atLeastOnce()).someMethod();復制代碼

這就是mock的誤區一:

Mockito.mock()并不是mock一整個類,而是根據傳進去的一個類,mock出屬于這個類的一個對象,并且返回這個mock對象;而傳進去的這個類本身并沒有改變,用這個類new出來的對象也沒有受到任何改變!

結合上面的例子,Mockito.mock(ArrayList.class);只是返回了一個屬于ArrayList這個類的一個mock對象。ArrayList這個類本身沒有受到任何影響,而 list 不是一個mock對象。Mockito.verify()的參數必須是mock對象,也就是說,Mockito只能驗證mock對象的方法調用情況。因此,上面那種寫法就出錯了。

誤區二

我們先看一個例子:public class LoginPresenter {

private UserLoginTask mAuthTask;

public void login(String email, String password) {

mAuthTask = new UserLoginTask(email, password);

//執行登錄操作

mAuthTask.execute();

}

}復制代碼

上面是一個登錄操作, 現在我們來驗證 login() 函數, 因為它沒有返回值,這時候我們只要驗證 execute() 有沒有執行就可以了。

@Test

public void testLogin() throws Exception {

UserLoginTask mockLoginTask = mock(UserLoginTask.class);

LoginPresenter loginPresenter = new LoginPresenter();

loginPresenter.login("jason@gmail.com", "123456");

//驗證是否執行 excute()

verify(mockLoginTask).excute();

}復制代碼

由于 UserLoginTask 繼承 AsyncTask, 所以會報錯,同誤區一中的問題一樣(not mock),這時候我們需要用到 Robolectric 框架,這個可以參考我

mock的誤區二:

mock出來的對象并不會自動替換掉正式代碼里面的對象,你必須要有某種方式把mock對象應用到正式代碼里面。

這個時候我們可以通過 構造方式將依賴傳進去,就 OK 了。

public class LoginPresenter {

private UserLoginTask mAuthTask; //===>

public LoginPresenter(UserLoginTask mAuthTask) {

//TODO test argument

//執行登錄操作

mAuthTask.execute(email, password);

}

}復制代碼

修改測試用例…

LoginPresenter loginPresenter = new LoginPresenter(mockLonginTask); //==>復制代碼

運行發現終于成功了, 不容易。。

驗證方法調用及參數

使用Mockito,驗證一個對象的方法調用情況:

Mockito.verify(objectToVerify).methodToVerify(arguments);

其中 objectToVerify 和 methodToVerify 對應上面的 mockedList 和 add,表示驗證 mockedList 的 add 方法是否傳入參數是 one。

很多時候你并不關心被調用方法的參數具體是什么,或者是你也不知道,你只關心這個方法得到調用了就行。這種情況下,Mockito 提供了一系列的 any 方法,來表示任何的參數都行。

anyString() 表示任何一個字符串都可以。類似 anyString,還有 anyInt, anyLong, anyDouble 等等。anyObject 表示任何對象,any(clazz) 表示任何屬于clazz的對象。 舉個栗子:@Test

public void testDoGet() throws IOException {

Http http = spy(new Http(5000, 5000));

URL url = createUrlConnection();

http.doGet(url, ContentType.HTML.str);

verify(http).createHttpUrlConnection(any(URL.class), any(Http.Method.class), anyString());

}復制代碼

指定 Mock 對象的某些方法的行為

那么接下來,我們就來介紹 Mock 的第二大作用,先介紹其中的第一點:指定 Mock 對象的某個方法返回特定的值。

我們見面的 login() 進行修改, 添加對網絡的判斷, 代碼如下:

public void login(String email, String password) {

//TODO test argument

if(!NetManager.isConnected()) { //添加網絡判斷===>

return;

}

//執行登錄操作

mAuthTask.execute(email, password);

}復制代碼

修改測試代碼:NetManagerWraper netManagerWraper = mock(NetManagerWraper.class); //==>

when(netManagerWraper.isConnected()).thenReturn(false); ==>復制代碼

下面我們說說怎么樣指定一個方法執行特定的動作,這個功能一般是用在目標的方法是 void 類型的時候。

現在假設我們的 LoginPresenter 的 login() 方法是這樣的://執行登錄操作, 并且處理網絡返回

mAuthTask.execute(email, password, new NetworkCallBack() {

@Override

public void onSuccess(Object data) {

}

@Override

public void onFailed(int code, String msg) {

}

});復制代碼

我們想進一步測試傳給 NetworkCallback 里面的代碼,驗證 view 得到了更新等等。在測試環境下,我們并不想依賴 excute 的真實邏輯,而是讓 mAuthTask

直接調用傳入的 NetworkCallback 的 onSuccess 或 onFailed 方法。這種指定 Mock 對象執行特定的動作的寫法如下:

`Mockito.doAnswer(desiredAnswer).when(mockObject).targetMethod(args);

測試代碼如下:

doAnswer(new Answer() {

@Override

public Object answer(InvocationOnMock invocation) throws Throwable {

//這里可以獲得傳給performLogin的參數

Object[] arguments = invocation.getArguments();

//callback是第三個參數

NetworkCallBack callback = (NetworkCallBack) arguments[2];

callback.onSuccess(null);

return null;

}

}).when(mockLonginTask).execute(anyString(), anyString(), any(NetworkCallBack.class));復制代碼

我們想在調用某些無返回值函數的時候拋出異常,那么可以使用 doThrow 方法。如果想簡單的指定目標方法“什么都不做”,那么可以使用 Mockito.doNothing()。如果你想讓目標方法調用真實的邏輯,可以使用 Mockito.doCallRealMethod()(默認不是的, 請看下文)。

Spy

如果我們不指定 Mock 對象方法的行為, 那么他是不是走真實邏輯呢? 答案是否定的。如果沒我們不指定它的行為,對于 Mock 對象的所有非 void 方法都將返回默認值 int,long 類型方法將返回0,boolean 方法將返回 false,對象方法將返回 null 等等;而 void 方法將什么都不做。

然而很多時候,你希望達到這樣的效果:除非指定,否者調用這個對象的默認實現,同時又能擁有驗證方法調用的功能。這正好是 spy 對象所能實現的效果。

創建Spy方式:

Mockito.spy(toMockObject);

通過注解的方式@Spy

@Test

public void testSpy() {

NetManagerWraper spy = spy(new NetManagerWraper());

assertTrue(spy.isConnected());

when(spy.isConnected()).thenReturn(false);

}復制代碼

spy 與 mock 的唯一區別就是默認行為不一樣: spy 對象的方法默認調用真實的邏輯,mock 對象的方法默認什么都不做,或直接返回默認值。

Mockito Annotation

通過 Mockito 注解可以快速創建 Mock 對象, 這樣對于我們這樣的懶人來說,是不是很爽。 上面我也簡單提到了, 我們可以通過 mock() 和 @Mock 創建, @Mock 就是通過注解的方式創建的, 由于我們使用注解, 當然我們要告訴 Mockito 框架, 不然它怎樣知道你使用注解了, 難道它是神嗎? 加上@Rule 就行了, 這樣JUnit Rule(?)就會每個測試方法測試前進行檢查。添加方法:@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();, 當然創建 spy 對象也可以加 @Spy。

寫在最后

上面的就是 Mockito 的基本使用, 當然由于并不是很全,更全面的可以看

上面代碼在

參考

總結

以上是生活随笔為你收集整理的android mock测试资源,Android 单元测试 --Mock 及 Mockito的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。