Unit-Tests mit JUnit
Schreiben Sie schnelle, zuverlässige Unit-Tests mit JUnit 4. Verwenden Sie @Test, @Before, @After und Assertions, testen Sie LiveData mit InstantTaskExecutorRule und Coroutines mit runTest.
Unit-Tests mit JUnit ist eine kostenlose Android Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Android Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Android Academy-Kurs umfasst insgesamt 4 Lektionen.
Warum Tests schreiben?
Tests sind kein Luxus — sie sind Ihr Sicherheitsnetz:
- Fehler erkennen, bevor es die Benutzer tun
- Mit Zuversicht refaktorieren (wenn die Tests erfolgreich sind, ist nichts kaputtgegangen)
- Das vorgesehene Verhalten dokumentieren
- Regressionen beim Hinzufügen neuer Funktionen verhindern
Gut getesteter Code ist außerdem oft besser entworfen. Wenn er schwer zu testen ist, sind die Komponenten wahrscheinlich zu eng gekoppelt.
Arten von Android-Tests
Zwei Kategorien:
- Unit-Tests (Ordner
test/) — laufen auf der JVM, kein Gerät erforderlich. Schnell. Testen reine Kotlin-/Java-Logik. - Instrumentierte Tests (Ordner
androidTest/) — laufen auf einem Gerät oder Emulator. Langsamer. Testen Android-spezifischen Code (Room-Datenbank, UI).
Bevorzugen Sie Unit-Tests für die Geschäftslogik. Verwenden Sie instrumentierte Tests nur, wenn Sie mit Android-APIs interagieren müssen.
JUnit-4-Einrichtung
JUnit 4 ist standardmäßig in Android-Projekten enthalten. Fügen Sie Folgendes zu app/build.gradle hinzu:
// app/build.gradle:
dependencies {
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
testImplementation 'androidx.arch.core:core-testing:2.2.0' // for LiveData
}Ihr erster JUnit-Test
Erstellen Sie eine Klasse in src/test/java/ und annotieren Sie Testmethoden mit @Test:
import org.junit.Test
import org.junit.Assert.*
class CalculatorTest {
private val calc = Calculator()
@Test
fun `addition returns correct sum`() {
val result = calc.add(2, 3)
assertEquals(5, result)
}
@Test
fun `division by zero throws exception`() {
assertThrows(ArithmeticException::class.java) {
calc.divide(10, 0)
}
}
}@Before und @After
Verwenden Sie Lifecycle-Annotationen, um den Zustand vor und nach jedem Test einzurichten beziehungsweise aufzuräumen:
class UserRepositoryTest {
private lateinit var repo: UserRepository
private lateinit var fakeDao: FakeUserDao
@Before
fun setUp() {
fakeDao = FakeUserDao() // fresh instance before each test
repo = UserRepository(fakeDao)
}
@After
fun tearDown() {
fakeDao.clear() // clean up after each test
}
@Test
fun `getUsers returns all users`() {
fakeDao.insert(User(1, "Alice"))
fakeDao.insert(User(2, "Bob"))
assertEquals(2, repo.getUsers().size)
}
}Häufige Assertions
JUnit stellt Assertion-Methoden in Assert.* bereit:
// Equality:
assertEquals(expected, actual)
assertNotEquals(unexpected, actual)
// Null:
assertNull(value)
assertNotNull(value)
// Boolean:
assertTrue(condition)
assertFalse(condition)
// Same object reference:
assertSame(expected, actual)
// Custom message on failure:
assertEquals("User ID should be 1", 1, user.id)
// Exception:
assertThrows(IllegalArgumentException::class.java) {
User(id = -1, name = "")
}Ein ViewModel testen
Um LiveData zu testen, fügen Sie die InstantTaskExecutorRule hinzu, damit LiveData synchron postet:
class UserViewModelTest {
@get:Rule
val instantTaskRule = InstantTaskExecutorRule()
private val fakeRepo = FakeUserRepository()
private lateinit var viewModel: UserViewModel
@Before
fun setUp() {
viewModel = UserViewModel(fakeRepo)
}
@Test
fun `users are loaded on init`() {
fakeRepo.usersToReturn = listOf(User(1, "Alice"), User(2, "Bob"))
viewModel.loadUsers()
val result = viewModel.users.value
assertNotNull(result)
assertEquals(2, result?.size)
}
}Coroutines testen
Verwenden Sie TestCoroutineDispatcher / StandardTestDispatcher, um die Ausführung von Coroutines in Tests zu steuern:
class SyncWorkerTest {
@get:Rule
val instantTaskRule = InstantTaskExecutorRule()
private val testDispatcher = StandardTestDispatcher()
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `sync completes successfully`() = runTest {
val repo = FakeRepository()
val worker = SyncUseCase(repo, testDispatcher)
val result = worker.run()
assertTrue(result.isSuccess)
}
}Fake oder Mock
Zwei Strategien, um echte Abhängigkeiten in Tests zu ersetzen:
- Fake — eine funktionsfähige, für Tests entwickelte Implementierung (z. B. eine Liste im Speicher anstelle einer echten Datenbank). Einfach zu schreiben, gut lesbar, keine Bibliothek erforderlich.
- Mock — ein automatisch generierter Stub, der Aufrufe aufzeichnet und Ihnen die Überprüfung von Interaktionen ermöglicht (Mockito, MockK). Leistungsfähiger, kann bei übermäßiger Verwendung jedoch instabil werden.
Bevorzugen Sie Fakes für einfache Fälle. Verwenden Sie Mocks, wenn Sie Methodenaufrufe überprüfen müssen.
Einen Fake schreiben
Ein Fake implementiert dieselbe Schnittstelle wie die echte Klasse, verwendet aber Speicher als Ablage:
interface UserDao {
fun getAll(): List<User>
fun insert(user: User)
}
class FakeUserDao : UserDao {
private val storage = mutableListOf<User>()
override fun getAll(): List<User> = storage.toList()
override fun insert(user: User) { storage.add(user) }
fun clear() { storage.clear() }
}Konvention für Testnamen
Gute Testnamen beschreiben, was getestet wird, und nennen das erwartete Ergebnis. Verwenden Sie in Kotlin Funktionsnamen in Backticks, um gut lesbare Beschreibungen zu erhalten:
`getUsers returns empty list when no users exist``login throws exception when password is blank``add returns correct sum for negative numbers`
Muster: `subject does X when Y`
Kurze Überprüfung
Welchen Zweck erfüllt @Before in einer JUnit-Testklasse?
Zusammenfassung: Unit-Tests mit JUnit
Zuverlässige Apps sind getestete Apps:
- Unit-Tests gehören in
src/test/und laufen auf der JVM — schnell - Mit
@Testannotieren undassertEquals,assertTruesowieassertThrowsverwenden @Before/@Afterfür Einrichtung und AufräumenInstantTaskExecutorRulezum synchronen Testen von LiveDatarunTest+StandardTestDispatcherzum Testen von Coroutines- Für einfache Ersetzungen Fakes gegenüber Mocks bevorzugen
Als Nächstes: Mocking mit Mockito zur Überprüfung von Interaktionen.
Häufig gestellte Fragen
Ist die Lektion „Unit-Tests mit JUnit“ kostenlos?
Ja — der vollständige Text von „Unit-Tests mit JUnit“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Android Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Android Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Unit-Tests mit JUnit“?
Schreiben Sie schnelle, zuverlässige Unit-Tests mit JUnit 4. Verwenden Sie @Test, @Before, @After und Assertions, testen Sie LiveData mit InstantTaskExecutorRule und Coroutines mit runTest. Du übst Android Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Android Academy zu starten?
Keine Vorkenntnisse erforderlich. Android Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.
Wie lange dauert die Lektion „Unit-Tests mit JUnit“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Android Academy-Lektion Code schreiben und ausführen?
Ja. Jede Android Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Unit-Tests mit JUnit
- Mocking mit Mockito
- UI-Tests mit Espresso
- Debugging und Profiling