建構本機單元測試

本機測試會直接在您的工作站執行,而非 Android 裝置或模擬器因此,它會使用您的本機 Java 虛擬機器 (JVM), 執行測試,而非 Android 裝置本機測試可讓您評估 能更快速地偵測應用程式邏輯但無法與 Android 架構會限制您可以執行的測試類型。

單元測試會驗證一小段程式碼 ( 測試。方法是執行程式碼並檢查結果。

單元測試通常很簡單,但如果單元測試 處於測試狀態的設計並未考量可測試性。

  • 您要驗證的程式碼必須可供測試存取。適用對象 例如,您無法直接測試私人方法。相反地 透過公用 API 存取
  • 如要在「隔離」中執行單元測試,請確認單元的依附元件。 測試中的元件必須替換為您控制的元件,例如 其他的測試替身。如果您的程式碼依賴 Android 架構

如要瞭解 Android 常見的單元測試策略,請參閱這篇文章 測試。

本機測試位置

根據預設,本機單元測試的來源檔案會放在 module-name/src/test/。您在建立新的目錄時,已有這個目錄 建立專案

新增測試依附元件

您也需要為專案設定測試依附元件,才能使用 JUnit 測試架構提供的標準 API。

如要這麼做,請開啟應用程式模組的 build.gradle 檔案,然後指定以下項目 做為依附元件請使用 testImplementation 函式來表示 套用至本機測試來源集,而非應用程式:

dependencies {
  // Required -- JUnit 4 framework
  testImplementation "junit:junit:$jUnitVersion"
  // Optional -- Robolectric environment
  testImplementation "androidx.test:core:$androidXTestVersion"
  // Optional -- Mockito framework
  testImplementation "org.mockito:mockito-core:$mockitoVersion"
  // Optional -- mockito-kotlin
  testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
  // Optional -- Mockk framework
  testImplementation "io.mockk:mockk:$mockkVersion"
}

建立本機單元測試類別

本機單元測試類別可用來編寫為 JUnit 4 測試類別。

方法是建立包含一或多個測試方法的類別,通常為 module-name/src/test/。測試方法以 @Test 註解開始 包含程式碼,用於練習及驗證元件的單一部分 。

以下範例說明如何實作本機單元測試類別。 嘗試驗證的emailValidator_correctEmailSimple_returnsTrue()測試方法 isValidEmail():這是應用程式內的方法。測試函式會傳回 如果isValidEmail() 也傳回 true,則為 true。

Kotlin

import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test

class EmailValidatorTest {
  @Test fun emailValidator_CorrectEmailSimple_ReturnsTrue() {
    assertTrue(EmailValidator.isValidEmail("name@email.com"))
  }

}

Java

import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

class EmailValidatorTest {
  @Test
  public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
    assertTrue(EmailValidator.isValidEmail("name@email.com"));
  }
}

建議您建立可讀取的測試,以評估應用程式中的元件是否 應用程式會傳回預期結果。建議您使用斷言程式庫,例如 格式為 junit.Assert、Hamcrest,或 Truth:上方的程式碼片段舉例說明 junit.Assert。

可模擬的 Android 程式庫

執行本機單元測試時,Android Gradle 外掛程式會包含 內含 Android 架構的所有 API 的程式庫, 專案中使用的版本程式庫存放了所有公開方法和 這些 API 的類別中,但方法中的程式碼已移除。如果有任何 方法存取時,此測試會擲回例外狀況。

這可讓您在參照 Android 中的類別時建立本機測試 例如 Context更重要的是,您可以使用模擬 與 Android 類別聯手

模擬 Android 依附元件

常見的問題是找出類別正在使用字串資源。你可以 呼叫 Context 中的 getString() 方法,即可取得字串資源 類別然而,本機測試無法使用 Context 或其任何方法, 隸屬於 Android 架構在理想情況下,對 getString() 的呼叫會是 中移出課程,但這並不總是實際。解決方法是 建立 Context 的模擬或虛設常式,且其會在其下列情況傳回相同的值 叫用 getString() 方法。

使用可模擬的 Android 程式庫和模擬架構,例如 Mockito 或 MockK,即可將 在單元測試中,Android 類別模擬的行為。

如要使用 Mockito 在本機單元測試中新增模擬物件,請按照下列步驟操作: 程式設計模型

  1. 在 build.gradle 檔案中加入 Mockito 程式庫依附元件,如 「設定測試環境」一文所述。
  2. 在單元測試類別定義的開頭,將 @RunWith(MockitoJUnitRunner.class) 註解。這個註解會指出 透過 Mockito 測試執行器來驗證您的架構使用方式是否正確, 可簡化模擬物件的初始化作業。
  3. 如要為 Android 依附元件建立模擬物件,請新增 @Mock 註解 。
  4. 如要虛設依附元件的行為,您可以指定條件並 使用 when() 和 thenReturn(),符合條件時傳回的值 方法。

以下範例說明如何建立使用模擬圖的單元測試 Kotlin 中的 Context 物件使用 Mockito-Kotlin 建立。

import android.content.Context
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock

private const val FAKE_STRING = "HELLO WORLD"

@RunWith(MockitoJUnitRunner::class)
class MockedContextTest {

  @Mock
  private lateinit var mockContext: Context

  @Test
  fun readStringFromContext_LocalizedString() {
    // Given a mocked Context injected into the object under test...
    val mockContext = mock<Context> {
        on { getString(R.string.name_label) } doReturn FAKE_STRING
    }

    val myObjectUnderTest = ClassUnderTest(mockContext)

    // ...when the string is returned from the object under test...
    val result: String = myObjectUnderTest.getName()

    // ...then the result should be the expected one.
    assertEquals(result, FAKE_STRING)
  }
}

如要進一步瞭解如何使用 Mockito 架構,請參閱 Mockito API 參照和 SharedPreferencesHelperTest 類別中的 程式碼範例。另外,也請嘗試使用 Android Testing Codelab。

錯誤:「方法 ... 未模擬」

如果您嘗試存取模擬 Android 程式庫的任何 傳回給 Error: "Method ... not mocked 訊息的方法。

如果擲回的例外狀況對測試造成問題,您可以更改 就會根據 傳回類型。如要這麼做,請在專案的 Groovy 中的頂層 build.gradle 檔案:

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }