Test Doubles — Arten von Ersatzobjekten und ihre Anwendung

Autor: IT Sectr Veröffentlicht: 2026-04-10 Lesezeit: 9 Min.

Test Doubles sind Ersatzobjekte, die in Modultests anstelle von echten Abhängigkeiten verwendet werden. Der Begriff wurde von Gerard Meszaros im Buch „xUnit Test Patterns“ (2007) als übergeordnetes Konzept für Mock, Stub, Fake, Spy und Dummy eingeführt. Laut Martin Fowler (2024) ermöglichen Test Doubles die Isolierung der zu testenden Komponente von ihrer Umgebung, wodurch Tests deterministisch, schnell und unabhängig von externen Diensten werden.

Wichtige Punkte

  • Test Doubles — Oberbegriff für alle Arten von Ersatzobjekten in Tests
  • Mock prüft die Interaktion: welche Methoden mit welchen Argumenten aufgerufen wurden
  • Stub gibt vordefinierte Werte zurück, ohne Aufrufe zu prüfen
  • Fake — vereinfachte funktionsfähige Implementierung (z. B. In-Memory-Datenbank)
  • Spy zeichnet Aufrufe zur späteren Überprüfung auf, Dummy füllt Parameter

Was sind Test Doubles?

Test Doubles ist ein Begriff aus der Automobilindustrie (Stuntdouble), der in die Softwareentwicklung übertragen wurde. Wie ein Stuntdouble einen Schauspieler in einer gefährlichen Szene ersetzt, ersetzt ein Test Double eine echte Komponente in einem Testszenario. Dies ist notwendig, wenn die echte Abhängigkeit nicht verfügbar, langsam, nicht deterministisch ist oder Nebenwirkungen hat.

Das Konzept der Test Doubles umfasst fünf spezifische Typen, die jeweils ihre eigene Aufgabe lösen. Die Typologie von Meszaros ist kanonisch und wird in allen modernen Testleitfäden verwendet. Der Unterschied zwischen den Typen liegt im Grad der Kontrolle und Überprüfung: vom einfachen Füllen von Parametern (Dummy) bis zur vollständigen Überprüfung der Aufrufsequenz (Mock).

Warum Test Doubles benötigt werden

Der Hauptzweck von Test Doubles ist die Isolierung des zu testenden Moduls. In der mobilen Entwicklung umfassen echte Abhängigkeiten API-Server, Datenbanken, Dateisysteme, Gerätesensoren und Systemdienste (LocationManager, Camera, Bluetooth). Die direkte Verwendung dieser Komponenten macht Tests langsam, zerbrechlich und umgebungsabhängig. Laut Google Testing Blog (2023) werden gut isolierte Modultests in Millisekunden ausgeführt, während Integrationstests in Sekunden und Minuten ausgeführt werden.

Fünf Arten von Test Doubles

Die Klassifikation von Gerard Meszaros umfasst fünf Arten von Test Doubles, die sich in Verhalten und Zweck unterscheiden. Den Unterschied zwischen ihnen zu verstehen, ist die Grundlage für kompetente Modultests.

Dummy

Dummy ist ein Objekt, das an die zu testende Methode übergeben wird, aber nie verwendet wird. Dummy wird nur benötigt, um die Methodensignatur zu erfüllen. In Kotlin ist dies oft null, emptyList() oder ein Objekt mit Stubs. Dummy sollte keine Logik enthalten — wenn es aufgerufen wird, sollte der Test fehlschlagen.

Fake

Fake ist eine vereinfachte, aber funktionsfähige Implementierung einer Schnittstelle. Im Gegensatz zu Mock und Stub enthält Fake echte Geschäftslogik, jedoch in vereinfachter Form. Ein klassisches Beispiel ist InMemoryUserRepository, das Daten in einer HashMap statt in einer Datenbank speichert. Fake wird verwendet, wenn Logik getestet werden muss, die vom Zustand abhängt, aber ohne den Overhead der echten Infrastruktur.

TypZweckBeispiel
DummyParameter füllennull, leeres Objekt
FakeFunktionsfähige vereinfachte ImplementierungInMemoryRepository
StubFestgelegten Wert zurückgebenwhen(api.getUser()).thenReturn(user)
SpyAufrufe zur Überprüfung aufzeichnenverify(spy).save(user)
MockInteraktion überprüfenverify(mock).sendEmail(email)

Stub

Stub gibt vordefinierte Werte für bestimmte Aufrufe zurück. Stub prüft nicht, ob er aufgerufen wurde — er liefert einfach Daten. In Mockito wird Stub über when(method).thenReturn(value) erstellt. Stub ist ideal für Tests, wenn eine Abhängigkeit einen bestimmten Wert zurückgeben soll, der Aufruf selbst jedoch nicht wichtig ist.

Spy

Spy ist ein Wrapper um ein echtes Objekt, der alle Aufrufe zur späteren Überprüfung aufzeichnet. Im Gegensatz zu Mock delegiert Spy Aufrufe an das echte Objekt, erlaubt aber die Überprüfung, dass sie stattgefunden haben. In Mockito wird Spy über spy(realObject) erstellt. Spy ist nützlich für partielles Mocking, wenn man ein echtes Objekt verwenden, aber einige Aufrufe überprüfen möchte.

Mock

Mock ist ein Objekt mit vordefinierten Aufruferwartungen. Mock überprüft, dass bestimmte Methoden mit bestimmten Argumenten und in einer bestimmten Reihenfolge aufgerufen wurden. Im Gegensatz zu Stub konzentriert sich Mock auf die Verhaltensüberprüfung und nicht auf die Datenrückgabe. Mock ist der leistungsfähigste und am häufigsten verwendete Test-Double-Typ in der mobilen Entwicklung.

Mock vs Stub: Hauptunterschiede

Der Unterschied zwischen Mock und Stub verursacht selbst bei erfahrenen Entwicklern häufig Verwirrung. Der Hauptunterschied liegt im Zweck: Stub prüft den Zustand (state verification), Mock prüft das Verhalten (behavior verification).

Stub beantwortet die Frage: „Hat der Code das richtige Ergebnis zurückgegeben?“. Mock beantwortet die Frage: „Hat der Code die richtigen Methoden mit den richtigen Argumenten aufgerufen?“. In der mobilen Entwicklung wird Stub verwendet, wenn das Ergebnis wichtig ist (z. B. Daten aus einem Repository), während Mock verwendet wird, wenn Nebenwirkungen wichtig sind (z. B. E-Mail senden, in eine Datenbank schreiben).

kotlin
// Stub: Zustandsprüfung
every { repository.getUsers() } returns listOf(user)
val result = useCase.getUsers()
assertEquals(1, result.size)

// Mock: Verhaltensprüfung
every { analytics.logEvent("purchase") } returns Unit
useCase.purchase(item)
verify { analytics.logEvent("purchase") }

Test Doubles-Beispiele in Kotlin

Praktische Beispiele aller fünf Typen von Test Doubles in Kotlin mit MockK — der beliebtesten Mocking-Bibliothek für Android-Projekte.

Fake: InMemoryUserRepository

kotlin
class InMemoryUserRepository : UserRepository {
    private val store = mutableMapOf<String, User>()

    override fun save(user: User) {
        store[user.email] = user
    }

    override fun findByEmail(email: String): User? {
        return store[email]
    }
}

Stub + Mock: UseCase-Test

kotlin
class RegisterUseCaseTest {
    private val api = mockk<AuthApi>()
    private val repo = spyk(InMemoryUserRepository())
    private val useCase = RegisterUseCase(api, repo)

    fun `register user successfully`() = runTest {
        // Stub: feste API-Antwort zurückgeben
        coEvery { api.register("test@test.com") } returns AuthResult.Success("token123")

        val result = useCase.execute("test@test.com")

        // Verify: prüfen, dass der Benutzer gespeichert wurde
        verify { repo.save(any()) }
        assertTrue(result.isSuccess())
    }
}

Dummy: Test mit ungenutztem Parameter

kotlin
data class Logger(val appContext: Context, val format: FormatType)

fun `test logger with dummy context`() {
    // Dummy: Context wird innerhalb von Logger nicht verwendet
    val dummyContext = mockk<Context>()
    val logger = Logger(dummyContext, FormatType.JSON)
    assertEquals(FormatType.JSON, logger.format)
}

Wann welcher Typ in der mobilen Entwicklung verwendet wird

Die Wahl des Test Double-Typs hängt davon ab, was genau getestet wird: Zustand, Verhalten oder Integration. In der mobilen Entwicklung für Android und iOS haben sich die folgenden Empfehlungen etabliert.

Für ViewModel und UseCase

Beim Testen von ViewModel verwenden Sie Mock für Abhängigkeiten, die Nebenwirkungen erzeugen (Repositories, Analytics, Navigation), und Stub für Abhängigkeiten, die Daten zurückgeben (API-Clients, ContentProvider). Dies ermöglicht die Überprüfung, dass das ViewModel sowohl Erfolgs- als auch Fehlerszenarien korrekt behandelt.

Für Repository und Datenschicht

Auf Repository-Ebene bevorzugen Sie Fake (In-Memory-Datenbankimplementierungen) und Stub (feste API-Antworten). Fake ermöglicht das Testen von Caching-Logik und Offline-Modus ohne Einrichtung von SQLite. Stub simuliert verschiedene HTTP-Status: 200, 404, 500, Timeout.

  • Modultests der Geschäftslogik — Mock für alle externen Abhängigkeiten, Dummy für ungenutzte Parameter
  • Integrationstests — Fake statt Mock (prüfen, dass Komponenten zusammenarbeiten)
  • UI-Tests — Stub für API-Antworten (über MockWebServer oder WireMock)
  • Caching-Tests — Fake für Datenbank (In-Memory statt Room/SQLite)
  • Asynchronitätstests — Mock mit Coroutine-Unterstützung (MockK + Turbine für Flow)

Häufige Fehler bei der Verwendung von Ersatzobjekten

Die falsche Verwendung von Test Doubles ist eine der häufigsten Ursachen für zerbrechliche Tests, die bei jeder Refaktorisierung brechen.

Over-Mocking: übermäßige Verwendung von Mock

Der häufigste Fehler ist, alles zu mocken. Wenn jede Abhängigkeit in einem Test durch einen Mock ersetzt wird, hört der Test auf, das tatsächliche Verhalten zu überprüfen. Mock sollte nur für externe Abhängigkeiten verwendet werden (Netzwerk, Datenbank, Dateisystem, Systemdienste). Interne Anwendungskomponenten (Value Object, Data Class, einfache Hilfsprogramme) sollten nicht ersetzt werden.

Under-Specification: unzureichende Spezifikation

Der zweite Fehler ist das Erstellen eines Mocks ohne Definition von Erwartungen. Wenn eine Methode ohne every / when aufgerufen wird, gibt Mock einen Standardwert zurück (null, 0, false). Dies kann zu falsch-positiven Tests führen, bei denen Mock stillschweigend null zurückgibt und der Test dies als korrektes Verhalten interpretiert.

Over-Verification: übermäßige Überprüfung

Der dritte Fehler ist die Überprüfung jedes Aufrufs jedes Mocks. Verify sollte nur für Aufrufe verwendet werden, die aus Sicht der Geschäftslogik kritisch wichtig sind. Übermäßige Überprüfung macht Tests zerbrechlich: Eine Änderung der Aufrufreihenfolge im Produktionscode zerbricht Tests, ohne das Verhalten zu ändern.

Häufig gestellte Fragen

Was ist der Unterschied zwischen Mock und Stub?

Stub gibt Daten zurück und prüft den Zustand (was zurückgegeben wurde), während Mock das Verhalten prüft (welche Methoden aufgerufen wurden). Stub = „gib X zurück“, Mock = „prüfe, dass Y mit Argument Z aufgerufen wurde“. In echten Tests fungiert ein Objekt oft gleichzeitig als Stub und Mock.

Wann sollte man Fake statt Mock verwenden?

Fake ist Mock vorzuziehen, wenn Logik getestet wird, die vom Zustand abhängt: Caching, Offline-Modus, Transaktionen. Fake (In-Memory-Implementierung) ermöglicht das Testen dieser Szenarien ohne zerbrechliche Verify-Aufrufe. Mock eignet sich besser zur Überprüfung des Datenversands: Analytics, Push, E-Mail.

Welche Test-Doubles-Bibliothek ist die beste für Android?

Für Android-Projekte in Kotlin wird MockK empfohlen. Es unterstützt Coroutinen, Suspend-Funktionen, versiegelte Klassen und Erweiterungsfunktionen ohne zusätzliche Konfiguration. Für Java-Projekte bleibt Mockito der Standard — die beliebteste Bibliothek mit umfangreicher Dokumentation.

Wie testet man Kotlin Flow mit Test Doubles?

Zum Testen von Kotlin Flow verwenden Sie die Bibliothek Turbine zusammen mit MockK. Turbine vereinfacht die Überprüfung von Flow-Emissionen: Sie können die Reihenfolge der Werte, den Abschluss des Streams und Ausnahmen überprüfen. Stub für Flow gibt flowOf(value) zurück, Mock prüft, ob der Flow gesammelt wurde.

Ist die Verwendung von Test Doubles in UI-Tests zulässig?

Ja, aber auf der Ebene der API-Antworten, nicht der UI-Komponenten. Die Bibliotheken MockWebServer (OkHttp) und WireMock ermöglichen das Mocken von HTTP-Antworten in UI-Tests. Die UI-Komponenten selbst (Compose, SwiftUI Views) sollten nicht ersetzt werden — ihr Verhalten wird durch Screenshot-Tests und Espresso getestet.

Zusammenfassung

  • Test Doubles — Oberbegriff für fünf Arten von Ersatzobjekten: Mock, Stub, Fake, Spy, Dummy
  • Mock prüft das Verhalten (verify), Stub gibt Daten zurück (thenReturn), Fake fungiert als vereinfachte echte Implementierung
  • Spy umhüllt ein echtes Objekt und zeichnet Aufrufe auf, Dummy füllt ungenutzte Parameter
  • Die Typologie von Gerard Meszaros ist die kanonische Klassifikation, die in allen modernen Mocking-Frameworks verwendet wird
  • Für Kotlin-Projekte wird MockK empfohlen, für Java — Mockito, für iOS — Cuckoo oder OHHTTPStubs
  • Häufige Fehler: Over-Mocking (alles ersetzen), Under-Specification (undefinierte Erwartungen), Over-Verification (übermäßiges Verify)
  • Fake ist Mock vorzuziehen beim Testen von zustandsbehafteter Logik — Caching, Offline-Modus und Transaktionen

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch