Tạo kiểm thử đơn vị cục bộ

Chương trình kiểm thử cục bộ chạy trực tiếp trên máy trạm của riêng bạn chứ không phải trên Android thiết bị hoặc trình mô phỏng. Do đó, ứng dụng này sử dụng Máy ảo Java (JVM) cục bộ của bạn, thay vì dùng thiết bị Android để chạy kiểm thử. Thử nghiệm cục bộ cho phép bạn đánh giá logic của ứng dụng nhanh hơn. Tuy nhiên, việc không thể tương tác với Khung Android tạo ra sự giới hạn về các loại kiểm thử bạn có thể chạy.

Kiểm thử đơn vị xác minh hành vi của một phần mã nhỏ, đơn vị trong thử nghiệm. Để thực hiện điều đó, ứng dụng sẽ thực thi mã đó và kiểm tra kết quả.

Kiểm thử đơn vị thường đơn giản nhưng thiết lập có thể gặp vấn đề khi đơn vị đang thử nghiệm không được thiết kế tập trung vào khả năng thử nghiệm:

  • Mã bạn muốn xác minh phải có thể truy cập được từ một quy trình kiểm thử. Cho ví dụ: bạn không thể kiểm thử trực tiếp một phương thức riêng tư. Thay vào đó, bạn sẽ kiểm thử lớp bằng các API công khai của nó.
  • Để chạy kiểm thử đơn vị khi cách ly, các phần phụ thuộc của đơn vị trong quá trình kiểm thử phải được thay thế bằng các thành phần mà bạn kiểm soát, chẳng hạn như hàng giả hoặc đối tượng kiểm thử khác. Điều này đặc biệt khó khăn nếu mã của bạn phụ thuộc vào khung Android.

Để tìm hiểu về các chiến lược kiểm thử đơn vị phổ biến trong Android, hãy đọc bài viết Nội dung cần thử nghiệm.

Địa điểm kiểm thử cục bộ

Theo mặc định, các tệp nguồn cho kiểm thử đơn vị cục bộ được đặt trong module-name/src/test/. Thư mục này đã tồn tại khi bạn tạo một thư mục mới dự án bằng Android Studio.

Thêm các phần phụ thuộc kiểm thử

Bạn cũng cần định cấu hình các phần phụ thuộc kiểm thử cho dự án để sử dụng các API chuẩn do khung kiểm thử JUnit cung cấp.

Để thực hiện việc này, hãy mở tệp build.gradle của mô-đun ứng dụng và chỉ định nội dung sau thư viện làm phần phụ thuộc. Dùng hàm testImplementation để cho biết mà chúng áp dụng cho nhóm tài nguyên kiểm thử cục bộ chứ không phải ứng dụng:

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"
}

Tạo một lớp kiểm thử đơn vị cục bộ

Bạn có thể viết lớp kiểm thử đơn vị cục bộ dưới dạng lớp kiểm thử JUnit 4.

Để thực hiện việc này, hãy tạo một lớp chứa một hoặc nhiều phương thức kiểm thử, thường là trong module-name/src/test/. Phương thức kiểm thử bắt đầu bằng chú thích @Test và chứa mã để thực thi và xác minh một khía cạnh duy nhất của thành phần mà bạn muốn kiểm thử.

Ví dụ sau đây minh hoạ cách triển khai một lớp kiểm thử đơn vị cục bộ. Chiến lược phát hành đĩa đơn phương pháp kiểm tra emailValidator_correctEmailSimple_returnsTrue()nỗ lực xác minh isValidEmail() là một phương thức trong ứng dụng. Hàm kiểm tra sẽ trả về true nếuisValidEmail() cũng trả về giá trị 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"));
  }
}

Bạn nên tạo các chương trình kiểm thử dễ đọc để đánh giá xem các thành phần trong ứng dụng trả về kết quả dự kiến. Bạn nên sử dụng thư viện câu nhận định, chẳng hạn như dưới dạng junit.Assert, Hamcrest hoặc Sự thật. Đoạn mã trên là một ví dụ về cách sử dụng junit.Assert.

Thư viện Android mô phỏng

Khi bạn thực thi kiểm thử đơn vị cục bộ, Trình bổ trợ Android cho Gradle sẽ bao gồm một thư viện chứa tất cả API của khung Android, chính xác với phiên bản được dùng trong dự án của bạn. Thư viện này lưu giữ tất cả các phương thức và phương thức công khai lớp của các API đó, nhưng mã bên trong phương thức đã bị xoá. Nếu có trong số các phương thức được truy cập thì bài kiểm thử sẽ gửi ra một ngoại lệ.

Điều này cho phép tạo các bài kiểm thử cục bộ khi tham chiếu các lớp trong Android chẳng hạn như Context. Quan trọng hơn, tính năng này cho phép bạn dùng nội dung mô phỏng khung với các lớp Android.

Mô phỏng các phần phụ thuộc Android

Một vấn đề điển hình là thấy rằng một lớp đang sử dụng tài nguyên chuỗi. Bạn có thể lấy tài nguyên chuỗi bằng cách gọi phương thức getString() trong Context . Tuy nhiên, quy trình kiểm thử cục bộ không thể sử dụng Context hoặc bất kỳ phương thức nào của nó vì chúng đều thuộc khung Android. Tốt nhất là nên gọi getString() bị chuyển ra khỏi lớp, nhưng việc này không phải lúc nào cũng thực tế. Giải pháp là tạo một bản mô phỏng hoặc mã giả lập Context luôn trả về cùng một giá trị khi Phương thức getString() đã được gọi.

Thông qua thư viện Android mô phỏng và các khung mô phỏng như Mockito hoặc MockK, bạn có thể lập trình hành vi mô phỏng của các lớp Android trong kiểm thử đơn vị.

Để thêm một đối tượng mô phỏng vào kiểm thử đơn vị cục bộ bằng Mockito, hãy làm theo hướng dẫn sau mô hình lập trình:

  1. Đưa phần phụ thuộc thư viện Mockito vào tệp build.gradle, dưới dạng như mô tả trong phần Thiết lập môi trường kiểm thử.
  2. Ở đầu phần định nghĩa lớp kiểm thử đơn vị, hãy thêm phương thức Chú giải @RunWith(MockitoJUnitRunner.class). Chú thích này cho Trình chạy thử nghiệm Mockito để xác thực rằng bạn sử dụng khung chính xác và giúp đơn giản hoá việc khởi chạy các đối tượng mô phỏng.
  3. Để tạo đối tượng mô phỏng cho phần phụ thuộc Android, hãy thêm chú giải @Mock trước khi khai báo trường.
  4. Để xác định hành vi của phần phụ thuộc, bạn có thể chỉ định một điều kiện và trả về giá trị khi đáp ứng điều kiện bằng cách sử dụng when()thenReturn() .

Ví dụ sau đây cho thấy cách bạn có thể tạo một kiểm thử đơn vị sử dụng một bản mô phỏng Đối tượng Context trong Kotlin được tạo bằng 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)
  }
}

Để tìm hiểu thêm về cách sử dụng khung Mockito, hãy xem API Mockito tham chiếu và lớp SharedPreferencesHelperTest trong mã mẫu. Ngoài ra, hãy thử tham gia Lớp học lập trình kiểm thử Android.

Lỗi: "Phương pháp ... không được mô phỏng"

Thư viện Android mô phỏng sẽ đưa ra trường hợp ngoại lệ nếu bạn cố truy cập vào bất kỳ với thông báo Error: "Method ... not mocked.

Nếu các ngoại lệ được gửi trở nên khó khăn cho thử nghiệm của bạn, bạn có thể thay đổi để các phương thức thay vì trả về giá trị rỗng hoặc 0, tuỳ thuộc vào loại dữ liệu trả về. Để thực hiện việc này, hãy thêm cấu hình sau vào tệp build.gradle cấp cao nhất trong Groovy:

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