构建本地单元测试

本地测试直接在您自己的工作站(而不是 Android 工作站)上运行 设备或模拟器因此,该方法会使用本地 Java 虚拟机 (JVM)、 而不是 Android 设备来运行测试借助本地测试 更快地处理应用逻辑不过,由于无法与 Android 框架对您可以运行的测试类型造成了限制。

单元测试会验证一小部分代码的行为, 测试。为此,它会执行该代码并检查结果。

单元测试通常很简单,但当单元测试 被测在设计时未考虑可测试性:

  • 要验证的代码必须能通过测试访问。对于 例如,您无法直接测试私有方法。您可以改为通过 使用其公共 API 访问 Cloud Storage 存储分区。
  • 为了隔离运行单元测试,单元的依赖项 必须替换为您控制的组件 其他测试替身。如果您的代码依赖于 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

Mockable Android 库

当您执行本地单元测试时,Android Gradle 插件会包含一个 库,其中包含 Android 框架的所有 API,并且正确设置为 版本。该库包含所有公共方法和 类,但方法中的代码已被移除。如果有 方法时,测试会抛出异常。

这样,当引用 Android 中的类时,就可以构建本地测试 框架,例如 Context。更重要的是,它允许您使用 框架和 Android 类。

模拟 Android 依赖项

一个典型的问题是发现某个类正在使用字符串资源。您可以 通过调用 Context 中的 getString() 方法来获取字符串资源 类。不过,本地测试无法使用 Context 或其任何方法, 属于 Android 框架。理想情况下,对 getString() 的调用为 但这有时并不实用。解决方法是 创建 Context 的模拟或存根,当其 调用 getString() 方法。

借助 Mockable Android 库和各种模拟框架,例如 MockitoMockK),您可以通过 Android 类模拟的行为。

如需使用 Mockito 向本地单元测试添加模拟对象,请按照下面的 编程模型:

  1. build.gradle 文件中添加 Mockito 库依赖项,如 设置测试环境中所述。
  2. 在单元测试类定义的开头,添加 @RunWith(MockitoJUnitRunner.class) 注解。此注解可告知 Mockito 测试运行程序,用于验证您对框架的使用是否正确, 可以简化模拟对象的初始化。
  3. 如需为 Android 依赖项创建模拟对象,请添加 @Mock 注解 。
  4. 要对依赖项行为进行存根,您可以指定条件并 使用 when()thenReturn() 在满足条件时返回值 方法。

以下示例展示了如何创建使用模拟的单元测试 使用 Mockito-Kotlin 创建的 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 reference 中的 SharedPreferencesHelperTest 类和 示例代码。此外,您也可以试用 Android 测试 Codelab

错误:“Method ... not mocked”

如果您尝试访问 Mockable Android 库的任何 方法替换为 Error: "Method ... not mocked 消息。

如果抛出的异常会给测试带来问题,您可以将 以便方法返回 null 或 0,具体取决于 返回值类型。为此,请在您项目的 Groovy 中的顶层 build.gradle 文件:

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