Lokale Einheitentests erstellen

Ein lokaler Test wird direkt auf Ihrer eigenen Workstation und nicht auf einem Android-Gerät ausgeführt Gerät oder Emulator nutzen. Es verwendet also Ihre lokale Java Virtual Machine (JVM), als mit einem Android-Gerät. Mit lokalen Tests können Sie die Logik Ihrer App zu optimieren. Da Sie jedoch nicht mit dem Android-Framework interagieren können, sind die Arten von Tests, die Sie ausführen können, eingeschränkt.

Mit einem Einheitentest wird das Verhalten eines kleinen Codeabschnitts, der Einheit unter testen. Dazu wird der Code ausgeführt und das Ergebnis überprüft.

Unit-Tests sind in der Regel einfach, aber ihre Einrichtung kann problematisch sein, wenn die getestete Einheit nicht auf Testbarkeit ausgelegt ist:

  • Der Code, den Sie bestätigen möchten, muss über einen Test zugänglich sein. So können Sie beispielsweise eine private Methode nicht direkt testen. Stattdessen testen Sie den Kurs mit seinen öffentlichen APIs.
  • Damit Unittests isoliert ausgeführt werden können, müssen die Abhängigkeiten der zu testenden Einheit durch von Ihnen gesteuerte Komponenten ersetzt werden, z. B. durch Fakes oder andere Test-Doubles. Das ist besonders problematisch, wenn Ihr Code vom Android-Framework abhängt.

Informationen zu gängigen Strategien für Einheitentests unter Android finden Sie unter Was Sie testen.

Speicherort für lokale Tests

Standardmäßig werden die Quelldateien für lokale Einheitentests an folgendem Ort platziert: module-name/src/test/ Dieses Verzeichnis ist bereits vorhanden, wenn Sie mit Android Studio ein neues Projekt erstellen.

Testabhängigkeiten hinzufügen

Außerdem müssen Sie die Testabhängigkeiten für Ihr Projekt so konfigurieren, dass die Standard-APIs des JUnit-Testframeworks verwendet werden.

Öffnen Sie dazu die build.gradle-Datei des Moduls Ihrer App und geben Sie die folgenden Bibliotheken als Abhängigkeiten an. Verwenden Sie die Funktion testImplementation, um anzugeben, dass sie sich auf die lokale Testquellengruppe und nicht auf die Anwendung beziehen:

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

Lokale Unit-Testklasse erstellen

Sie schreiben Ihre lokale Unit-Testklasse als JUnit 4-Testklasse.

Erstellen Sie dazu eine Klasse mit einer oder mehreren Testmethoden, in der Regel in module-name/src/test/. Eine Testmethode beginnt mit der Anmerkung @Test und enthält den Code zum Testen und Verifizieren eines einzelnen Aspekts der Komponente, die Sie testen möchten.

Das folgende Beispiel zeigt, wie eine lokale Einheitentestklasse implementiert wird. Die Testmethode emailValidator_correctEmailSimple_returnsTrue() versucht, isValidEmail() zu überprüfen, eine Methode innerhalb der App. Die Testfunktion gibt „wahr“ zurück, wenn isValidEmail() auch „wahr“ zurückgibt.

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

Sie sollten lesbare Tests erstellen, mit denen Sie prüfen, ob die Komponenten in Ihrer App die erwarteten Ergebnisse zurückgeben. Wir empfehlen die Verwendung einer Assertion-Bibliothek wie als junit.Assert, Hamcrest oder Truth: Das obige Snippet ist ein Beispiel für die Verwendung von junit.Assert.

Mockable Android-Bibliothek

Wenn Sie lokale Einheitentests ausführen, enthält das Android-Gradle-Plug-in ein Bibliothek, die alle APIs des Android-Frameworks enthält, die in Ihrem Projekt verwendet wird. Die Bibliothek enthält alle öffentlichen Methoden und Klassen dieser APIs, aber der Code innerhalb der Methoden wurde entfernt. Falls vorhanden der Methoden aufgerufen wird, löst der Test eine Ausnahme aus.

So können lokale Tests erstellt werden, wenn auf Klassen im Android-Framework verwiesen wird, z. B. Context. Noch wichtiger ist, dass Sie eine Simulation verwenden können, -Framework mit Android-Klassen.

Android-Abhängigkeiten simulieren

Ein typisches Problem besteht darin, festzustellen, ob eine Klasse eine Zeichenfolgenressource verwendet. Sie können Stringressourcen durch Aufrufen der Methode getString() im Context abrufen . In einem lokalen Test können Context oder eine ihrer Methoden jedoch nicht verwendet werden, gehören zum Android-Framework. Im Idealfall wäre der Aufruf von getString() aus dem Kurs gezogen, aber das ist nicht immer praktikabel. Die Lösung besteht darin, einen Mock oder einen Stub von Context erstellen, der immer denselben Wert zurückgibt, Die Methode getString() wird aufgerufen.

Mit der Mockable Android-Bibliothek und Mocking-Frameworks wie Mit Mockito oder MockK können Sie den von Modellen der Android-Klassen in Ihren Einheitentests.

So fügen Sie Ihrem lokalen Einheitentest mit Mockito ein simuliertes Objekt hinzu: Programmiermodell:

  1. Fügen Sie die Abhängigkeit von der Mockito-Bibliothek in Ihre build.gradle-Datei ein, wie unter Testumgebung einrichten beschrieben.
  2. Fügen Sie am Anfang der Definition der Einheitentestklasse den Parameter @RunWith(MockitoJUnitRunner.class)-Anmerkung. Diese Anmerkung weist den Mockito-Test-Runner an, die korrekte Verwendung des Frameworks zu prüfen und vereinfacht die Initialisierung Ihrer Mock-Objekte.
  3. Wenn Sie ein Mock-Objekt für eine Android-Abhängigkeit erstellen möchten, fügen Sie die Annotation @Mock vor der Felddeklaration hinzu.
  4. Um das Verhalten der Abhängigkeit zu durchsuchen, können Sie eine Bedingung angeben und Rückgabewert, wenn die Bedingung mithilfe von when() und thenReturn() erfüllt ist .

Im folgenden Beispiel sehen Sie, wie Sie einen Unittest erstellen, der eine Simulation verwendet. Das Objekt Context in Kotlin, das mit Mockito-Kotlin erstellt wurde.

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

Weitere Informationen zur Verwendung des Mockito-Frameworks finden Sie in der Mockito API-Referenz und in der Klasse SharedPreferencesHelperTest im Beispielcode. Sehen Sie sich auch das Codelab zum Testen von Android-Apps an.

Fehler: "Method ... not mocked"

Die Mockable Android-Bibliothek wirft eine Ausnahme, wenn Sie versuchen, mit der Meldung Error: "Method ... not mocked auf eine ihrer Methoden zuzugreifen.

Wenn die geworfenen Ausnahmen für Ihre Tests problematisch sind, können Sie das Verhalten so ändern, dass Methoden je nach Rückgabetyp entweder null oder null zurückgeben. Fügen Sie dazu die folgende Konfiguration im Top-Level-build.gradle-Datei in Groovy:

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