建構本機單元測試

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

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

單元測試通常很簡單,但如果測試中的單元並未以可測試性為設計考量,則其設定可能會出現問題:

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

如要瞭解 Android 中常見的單元測試策略,請參閱「要測試的項目」。

本機測試位置

根據預設,本機單元測試的原始檔案會放在 module-name/src/test/ 中。使用 Android Studio 建立新專案時,這個目錄就會存在。

新增測試依附元件

您還需要為專案設定測試依附元件,以便使用 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.AssertHamcrestTruth。上方的程式碼片段是如何使用 junit.Assert 的範例。

可模擬的 Android 程式庫

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

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

模擬 Android 依附元件

常見的問題是找出類別正在使用字串資源。你可以 呼叫 Context 中的 getString() 方法,即可取得字串資源 類別不過,本機測試無法使用 Context 或任何 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 中使用 Mockito-Kotlin 建立的模擬 Context 物件,建立單元測試。

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
  }