原文:https://developer.android.com/training/testing/unit-testing/local-unit-tests.html
如果你的單元測試沒有依賴或者只有簡單的Android依賴,則應該在本地開發機器上運行測試。這種測試方法非常高效,因為它可以幫助你避免每次運行測試時將目標應用程序和單元測試代碼加載到真機或模擬器上的開銷。因此,運行單元測試的執行時間大大減少了。通過這種方法,你通常使用mock框架(如Mockito)來完成任何依賴關系。
### 設置測試環境
在你的Android Studio項目中,必須將本地單元測試的源文件存儲在module-name/src/test/java/ 目錄中。在創建新項目時,該目錄已經存在。
你還需要配置項目的測試依賴,以使用JUnit 4框架提供的標准API。如果你的測試需要與Android依賴關系進行交互,請包含Mockito庫以簡化本地單元測試。要了解有關在本地單元測試中使用模擬對象的更多信息,請參閱模擬Android依賴關系。
在你的App程序的目錄下找到build.gradle文件中,將這些庫指定為依賴項:
dependencies {
// Required -- JUnit 4 framework
testCompile 'junit:junit:4.12'
// Optional -- Mockito framework
testCompile 'org.mockito:mockito-core:1.10.19'
}
### 創建本地單元測試類
你的本地單元測試類應該寫成一個JUnit 4測試類。 JUnit是Java最流行和廣泛使用的單元測試框架。這個框架的最新版本,JUnit 4,允許你用比前一版本更清晰,更靈活的方式編寫測試。與以前的基於JUnit 3的Android單元測試方法(使用JUnit 4)不同,你不需要擴展junit.framework.TestCase類。也不需要在測試方法名稱前加上“test”關鍵字,或者使用junit.framework或junit.extensions包中的任何類。
要創建基本的JUnit 4測試類,請創建一個包含一個或多個測試方法的Java類。 測試方法從 @Test
注釋開始,包含代碼來練習和驗證要測試的組件中的單個功能。
以下示例顯示了如何實現本地單元測試類。 測試方法emailValidator_CorrectEmailSimple_ReturnsTrue
驗證被測試的應用程序中的isValidEmail()
方法是否返回正確的結果。
import org.junit.Test;
import java.util.regex.Pattern;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class EmailValidatorTest {
@Test
public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
assertThat(EmailValidator.isValidEmail("name@email.com"), is(true));
}
...
}
要測試應用程序中的組件是否會返回預期的結果,請使用junit.Assert方法執行驗證檢查(或斷言),以便將待測組件的狀態與某個預期值進行比較。 為了使測試更具可讀性,可以使用Hamcrest匹配器(如is()和equalTo()方法)將返回的結果與期望的結果進行匹配。
### Mock Android依賴
默認情況下,針對Gradle的Android插件將針對android.jar庫的修改版本執行本地單元測試,該庫不包含任何實際的代碼。 相反,從你的單元測試方法調用Android類拋出一個異常。 這是為了確保只測試你的代碼,而不依賴於Android平台的任何特定行為(你沒有明確地mock)。
你可以使用mock框架在代碼中刪除外部依賴項,以便以預期的方式輕松測試組件與依賴項的交互。 通過用mock對象代替Android依賴關系,可以將單元測試與Android系統的其余部分分離,同時驗證這些依賴關系中正確的方法被調用。Java的Mockito模擬框架(版本1.9.5及更高版本)提供了與Android單元測試的兼容性。借助Mockito可以配置模擬對象以在調用時返回某個特定的值。
要使用此框架將mock對象添加到本地單元測試中,請遵循以下編程模型:
1、在你的 build.gradle 文件中包含Mockito庫依賴項,如設置上面的測試環境中所述。
2、在單元測試類定義的開始處,添加 @RunWith(MockitoJUnitRunner.class)
注釋。 這個注釋告訴Mockito測試運行器驗證你對框架的使用是否正確,並且簡化了你的模擬對象的初始化。
3、要為Android依賴項創建一個模擬對象,請在字段聲明之前添加@Mock注釋。
4、為了Stub依賴的行為,可以通過使用when()
和return()
方法來滿足條件時,可以指定一個條件和返回值。
以下示例顯示如何創建使用模擬Context對象的單元測試。
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import android.content.SharedPreferences;
@RunWith(MockitoJUnitRunner.class)
public class UnitTestSample {
private static final String FAKE_STRING = "HELLO WORLD";
@Mock
Context mMockContext;
@Test
public void readStringFromContext_LocalizedString() {
// Given a mocked Context injected into the object under test...
when(mMockContext.getString(R.string.hello_word))
.thenReturn(FAKE_STRING);
ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
// ...when the string is returned from the object under test...
String result = myObjectUnderTest.getHelloWorldString();
// ...then the result should be the expected one.
assertThat(result, is(FAKE_STRING));
}
}
要了解有關使用Mockito框架的更多信息,請參閱示例代碼中的Mockito API參考和SharedPreferencesHelperTest類。
### Error: "Method ... not mocked"
如果您運行測試,從Android SDK調用API,你不會使用mock,可能會收到一個錯誤,說這種方法沒有被模擬。 這是因為用於運行單元測試的android.jar文件不包含任何當前代碼(這些API僅由設備上的Android系統映像提供)。
相反,所有方法默認都會拋出異常。 這是為了確保你的單元測試你的代碼,而不是依賴於Android平台的任何特定的行為(你沒有明確地mock,如Mockito)。
如果拋出的異常說你的測試有問題,可以更改行為,以便通過在項目的頂級build.gradle文件中添加以下配置來返回null或零:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
注意:將returnDefaultValues屬性設置為true應該小心。 null / zero返回值可以在測試中引入回歸,這些回調很難調試,並且可能允許失敗的測試通過。只能用它作為最后的手段。
### 運行本地單元測試
要運行您的本地單元測試,請按照下列步驟操作:
1、通過單擊工具欄中的“ Sync Project”,確保您的項目與Gradle同步。
2、以下列其中一種方式運行測試:
- 要運行單個測試,請打開“Project”窗口,然后右鍵單擊以進行測試,然后單擊“Run”。
- 要測試類中的所有方法,請右鍵單擊測試文件中的類或方法,然后單擊“Run”。
- 要在目錄中運行所有測試,請右鍵單擊該目錄並選擇“Run Tests”。