建構本機單元測試

本機測試會直接在您的工作站執行,而非 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.AssertHamcrest,或 Truth:上方的程式碼片段舉例說明 junit.Assert

可模擬的 Android 程式庫

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

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

模擬 Android 依附元件

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

使用可模擬的 Android 程式庫和模擬架構,例如 MockitoMockK,即可將 在單元測試中,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
  }