Android Coden
Android 4 min lesen

Network Testing: API-Verhalten mit Fake-Servern und Fixtures testen

Fake-Server und Fixtures machen API-Tests deterministisch und reproduzierbar. So prüfst du Fehlerszenarien zuverlässig ohne echtes Backend.

Netzwerktests gehören zu den zuverlässigsten Qualitätssicherungswerkzeugen in der Android-Entwicklung. Statt ein echtes Backend anzusprechen, ersetzt du es durch einen kontrollierten Fake-Server und definierst exakt, welche Antworten deine App erhält. Das macht Tests deterministisch, schnell und vollständig unabhängig von externen Netzwerkverbindungen.

Was ist das?

Network Testing bezeichnet das Testen von Code, der HTTP-Anfragen stellt und Antworten verarbeitet – ohne dabei ein echtes Backend zu benötigen. Stattdessen verwendest du einen Fake-Server, der lokale Testantworten zurückliefert, oder du isolierst die Netzwerkschicht hinter einem Interface und injizierst im Test eine kontrollierte Implementierung.

Im Android-Kontext sitzt Netzwerkcode typischerweise im Data Layer – in Repositories und RemoteDataSources. Genau dort setzt Network Testing an: Du prüfst nicht die Benutzeroberfläche, sondern die Logik, die aus API-Antworten Domänenobjekte macht – inklusive aller Fehlerpfade, die in einem manuellen Test kaum zuverlässig provozierbar wären.

Das Kernziel ist Vorhersagbarkeit. Statt auf einen Server zu warten, der möglicherweise offline ist oder Testdaten verändert, lieferst du deinem Code vorgefertigte Antworten – sogenannte Fixtures – und überprüfst, wie er damit umgeht.

Wie funktioniert es?

Die verbreitetste Methode für lokale Netzwerktests in Android ist MockWebServer aus der OkHttp-Bibliothek. MockWebServer startet einen echten HTTP-Server auf localhost und lässt dich Antworten vorab in eine Warteschlange laden. Dein Produktionscode bemerkt keinen Unterschied, solange du die Basis-URL im Test als Abhängigkeit injizierst.

MockWebServer Grundmechanik

  1. Du startest MockWebServer im Test-Setup (@Before).
  2. Du konfigurierst die Basis-URL deines Retrofit- oder Ktor-Clients auf den localhost-Port des Servers.
  3. Du enqueuest MockResponse-Objekte mit definierten Status-Codes, Headern und Body-Inhalten.
  4. Dein Code macht eine echte HTTP-Anfrage gegen localhost – MockWebServer antwortet sofort.
  5. Nach dem Aufruf prüfst du mit server.takeRequest(), welche Anfragen tatsächlich ankamen (Methode, Pfad, Header).

Fixtures

Fixtures sind JSON-Dateien im Verzeichnis src/test/resources/. Sie enthalten realistische Beispielantworten, die du aus der echten API kopiert oder manuell erstellt hast. Das hält deinen Testcode lesbar: kein langer JSON-String im Quelltext, und verschiedene Szenarien lassen sich als separate Dateien pflegen (user_success.json, user_not_found.json, server_error.json).

Fehlerszenarien

Neben Erfolgsantworten testest du explizit Fehlerfälle:

  • HTTP 4xx – Client-Fehler wie 404 Not Found oder 401 Unauthorized
  • HTTP 5xx – Server-Fehler wie 500 Internal Server Error
  • Timeouts – über MockResponse.setBodyDelay() simuliert
  • Fehlerhafte Payloads – JSON mit falschen Typen oder fehlenden Pflichtfeldern, die den Parser zum Absturz bringen sollen

In der Praxis

Hier ein vollständiges Beispiel mit OkHttp MockWebServer und Retrofit in einem JUnit-Test:

import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import org.junit.After
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull

class UserRepositoryTest {

    private lateinit var mockWebServer: MockWebServer
    private lateinit var api: UserApi

    @Before
    fun setUp() {
        mockWebServer = MockWebServer()
        mockWebServer.start()

        api = Retrofit.Builder()
            .baseUrl(mockWebServer.url("/"))
            .client(OkHttpClient.Builder().build())
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(UserApi::class.java)
    }

    @After
    fun tearDown() {
        mockWebServer.shutdown()
    }

    @Test
    fun `lädt Benutzer erfolgreich bei HTTP 200`() {
        val fixture = javaClass.classLoader!!
            .getResourceAsStream("user_success.json")!!
            .bufferedReader().readText()

        mockWebServer.enqueue(
            MockResponse()
                .setResponseCode(200)
                .setBody(fixture)
        )

        val result = api.getUser(id = 1).execute()

        assertEquals(200, result.code())
        assertEquals("Max Mustermann", result.body()?.name)
    }

    @Test
    fun `gibt Fehler zurück bei HTTP 404`() {
        mockWebServer.enqueue(
            MockResponse().setResponseCode(404)
        )

        val result = api.getUser(id = 999).execute()

        assertEquals(404, result.code())
        assertNull(result.body())
    }
}

Der Test für den 404-Fall ist genauso wichtig wie der Erfolgsfall. Nur wer beide schreibt, weiß, dass sein Repository-Code auf Fehlerantworten überhaupt reagiert und keinen Absturz produziert.

Typische Stolperfalle: hart verdrahtete Basis-URL

Ein häufiger Fehler: Die Retrofit-Instanz wird mit "https://api.example.com" fest verdrahtet und ist im Test nicht austauschbar. Das macht Network Testing unmöglich, ohne den Produktionscode zu verändern. Die Lösung ist, die Basis-URL immer als Abhängigkeit zu übergeben – entweder über den Dependency-Injection-Graph (Hilt, Koin) oder als Konstruktorparameter des Repositories. Sobald der Data Layer sauber entkoppelt ist, brauchst du MockWebServer nur einzustecken und kannst jeden Netzwerkpfad gezielt testen.

Fazit

Network Testing ist kein optionaler Komfort, sondern ein konkreter Qualitätsanker für jeden Android-Code, der HTTP-Anfragen stellt. Mit MockWebServer, aussagekräftigen Fixtures und expliziten Fehlerszenarien deckst du genau die Randfälle ab, die in Produktion zu schwer reproduzierbaren Bugs führen. Schau dir deinen aktuellen Data Layer an: Kannst du die Basis-URL deines Netzwerk-Clients problemlos auf einen anderen Port umleiten? Wenn nicht, ist das ein konkretes Refactoring-Ziel. Schreib danach mindestens einen Test für den Erfolgsfall und einen für einen Server-Fehler – und beobachte, ob deine Fehlerbehandlung wirklich das tut, was du erwartest.

Quellen (3)
Redaktion

Geschrieben von

Redaktion

Das Redaktionsteam recherchiert und schreibt Artikel zu aktuellen Themen rund um Tech, Lifestyle und Ratgeber.