Ein lokaler Test wird direkt auf Ihrer eigenen Workstation ausgeführt und nicht auf einem Android-Gerät oder Emulator. Daher wird zum Ausführen von Tests Ihre lokale Java Virtual Machine (JVM) und nicht ein Android-Gerät verwendet. Mit lokalen Tests lässt sich die Logik Ihrer App schneller auswerten. Wenn Sie jedoch nicht mit dem Android-Framework interagieren können, schränken Sie die Arten der Tests ein, die Sie ausführen können.
Mit einem Einheitentest wird das Verhalten eines kleinen Codeabschnitts, der zu testenden Einheit, überprüft. Dazu wird dieser Code ausgeführt und das Ergebnis überprüft.
Einheitentests sind in der Regel einfach, ihre Einrichtung kann jedoch problematisch sein, wenn die zu testende Einheit nicht im Hinblick auf die Testbarkeit entwickelt wurde:
- Der Code, den Sie bestätigen möchten, muss in einem Test zugänglich sein. Sie können eine private Methode beispielsweise nicht direkt testen. Stattdessen testen Sie die Klasse mit ihren öffentlichen APIs.
- Damit Einheitentests isoliert ausgeführt werden, müssen die Abhängigkeiten der zu testenden Einheit durch von Ihnen gesteuerte Komponenten ersetzt werden, z. B. Fälschungen oder andere Test-Doubles. Dies ist besonders problematisch, wenn Ihr Code vom Android-Framework abhängt.
Informationen zu gängigen Strategien für Einheitentests in Android finden Sie unter Zu testende Elemente.
Standort für lokale Tests
Standardmäßig werden die Quelldateien für lokale Einheitentests in module-name/src/test/
gespeichert. Dieses Verzeichnis ist bereits vorhanden, wenn Sie ein neues Projekt mit Android Studio erstellen.
Testabhängigkeiten hinzufügen
Außerdem müssen Sie die Testabhängigkeiten für Ihr Projekt so konfigurieren, dass die vom JUnit-Test-Framework bereitgestellten Standard-APIs verwendet werden.
Öffnen Sie dazu die Datei build.gradle
Ihrer Anwendung und geben Sie die folgenden Bibliotheken als Abhängigkeiten an. Geben Sie mit der Funktion testImplementation
an, dass sie für die lokale Testquelle und nicht für die Anwendung gelten:
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 Einheitentestklasse erstellen
Sie schreiben Ihre lokale Unittest-Klasse als JUnit 4-Testklasse.
Erstellen Sie dazu eine Klasse, die eine oder mehrere Testmethoden enthält, normalerweise in module-name/src/test/
. Eine Testmethode beginnt mit der Annotation @Test
und enthält den Code, der ausgeführt und ein einzelner Aspekt der zu testenden Komponente geprüft wird.
Das folgende Beispiel zeigt, wie eine lokale Einheitentestklasse implementiert wird. Mit der Testmethode emailValidator_correctEmailSimple_returnsTrue()
wird versucht, die Methode isValidEmail()
zu überprüfen, da es sich um eine Methode innerhalb der App handelt. Die Testfunktion gibt „true“ zurück, wenn isValidEmail()
ebenfalls „true“ 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, die bewerten, ob die Komponenten in Ihrer Anwendung die erwarteten Ergebnisse zurückgeben. Wir empfehlen die Verwendung einer Assertion-Bibliothek wie 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 eine Bibliothek, die alle APIs des Android-Frameworks enthält, und zwar in der jeweils in Ihrem Projekt verwendeten Version. Die Bibliothek enthält alle öffentlichen Methoden und Klassen dieser APIs. Der Code innerhalb der Methoden wurde jedoch entfernt. Wenn auf eine der Methoden zugegriffen wird, gibt der Test eine Ausnahme aus.
Dadurch können lokale Tests erstellt werden, wenn auf Klassen im Android-Framework wie Context
verwiesen wird. Und was noch wichtiger ist: Sie können ein Mocking-Framework
mit Android-Klassen verwenden.
Mocking von Android-Abhängigkeiten
Ein typisches Problem besteht darin, herauszufinden, ob eine Klasse eine String-Ressource verwendet. Sie können Stringressourcen abrufen, indem Sie die Methode getString()
in der Klasse Context
aufrufen. Ein lokaler Test kann jedoch weder Context
noch eine der zugehörigen Methoden verwenden, da sie zum Android-Framework gehören. Idealerweise wird der Aufruf von getString()
aus der Klasse entfernt. Das ist jedoch nicht immer praktisch. Die Lösung besteht darin, einen Mock oder einen Stub von Context
zu erstellen, der immer denselben Wert zurückgibt, wenn die Methode getString()
aufgerufen wird.
Mit der Mockable Android-Bibliothek und Mocking-Frameworks wie Mockito oder MockK können Sie das Verhalten von Modellen der Android-Klassen in Ihren Einheitentests programmieren.
Wenn Sie Ihrem lokalen Einheitentest mit Mockito ein simuliertes Objekt hinzufügen möchten, folgen Sie diesem Programmiermodell:
- Fügen Sie die Abhängigkeit der Mockito-Bibliothek in die Datei
build.gradle
ein, wie unter Testumgebung einrichten beschrieben. - Fügen Sie am Anfang der Unittest-Klassendefinition die Annotation
@RunWith(MockitoJUnitRunner.class)
hinzu. Diese Annotation weist den Mockito-Test-Runner an, zu validieren, dass Sie das Framework korrekt verwendet haben, und vereinfacht die Initialisierung Ihrer Mock-Objekte. - Wenn Sie ein Mock-Objekt für eine Android-Abhängigkeit erstellen möchten, fügen Sie vor der Felddeklaration die Annotation
@Mock
hinzu. - Mit den Methoden
when()
undthenReturn()
können Sie eine Bedingung und einen Rückgabewert angeben, wenn die Bedingung erfüllt ist.
Das folgende Beispiel zeigt, wie Sie einen Einheitentest erstellen, der ein Context
-Beispielobjekt in Kotlin verwendet, 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 Referenz zur Mockito API und in der Klasse SharedPreferencesHelperTest
im Beispielcode. Sehen Sie sich auch das Android Testing Codelab an.
Fehler: „Method ... not mocked“
Die Mockable Android-Bibliothek gibt eine Ausnahme aus, wenn Sie versuchen, mit der Nachricht Error: "Method ... not mocked
auf eine ihrer Methoden zuzugreifen.
Wenn die ausgegebenen Ausnahmen für Ihre Tests problematisch sind, können Sie das Verhalten so ändern, dass die Methoden je nach Rückgabetyp stattdessen entweder null oder null zurückgeben. Fügen Sie dazu die folgende Konfiguration in der obersten build.gradle
-Datei Ihres Projekts in Groovy ein:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}