Wenn Warenkorb, Zahlungsdienst und Lagerverwaltung einzeln funktionieren, ist der Auftrag trotzdem nicht automatisch sicher. Genau hier setzt integration testing an: Mehrere zuvor isoliert geprüfte Komponenten werden gemeinsam getestet, damit Fehler an Schnittstellen, Datenformaten und Abläufen sichtbar werden. Ich zeige, was Integrationstests leisten, wie sie sich von Unit- und Systemtests unterscheiden und wie ein verlässlicher Testablauf mit Datenbank, API und Nachrichtenwarteschlange aussieht.
Die wichtigsten Entscheidungen für belastbare Integrationstests
- Schnittstellen sind der wichtigste Prüfpunkt, nicht nur die einzelnen Funktionen.
- Unit-Tests prüfen isolierte Logik, Integrationstests das Zusammenspiel mehrerer Komponenten.
- Schmale Tests mit einer echten Grenze liefern meist schnelleres und klareres Feedback als große End-to-End-Szenarien.
- Datenbank, REST-API, Dateisystem und Message Broker verdienen eigene Integrationsprüfungen.
- Reproduzierbare Testumgebungen sind wichtiger als eine möglichst große Zahl an Testfällen.

Was Integrationstests wirklich prüfen
Ein Integrationstest untersucht, ob mehrere unabhängig entwickelte Teile eines Softwaresystems korrekt zusammenarbeiten. Das können Module innerhalb einer Anwendung sein, aber auch eine Anwendung mit einer Datenbank, einem externen Zahlungsdienst oder einem Message Broker.
Die ISTQB beschreibt Integrationstests als Teststufe, die sich auf Interaktionen zwischen Komponenten oder Systemen konzentriert. Praktisch bedeutet das: Nicht nur das Ergebnis einer einzelnen Methode zählt, sondern auch die Frage, ob Daten richtig serialisiert, übertragen, verarbeitet und gespeichert werden.
Ein typisches Beispiel ist ein deutscher Online-Shop. Der Kunde bezahlt per SEPA oder Kreditkarte, der Zahlungsdienst bestätigt die Transaktion, der Shop aktualisiert den Bestellstatus und das Warenlager erhält einen Versandauftrag. Jede Funktion kann einzeln korrekt sein und der Gesamtprozess trotzdem scheitern, wenn etwa ein Feld anders heißt oder ein Statuswert falsch interpretiert wird.
Wo die Tests zwischen Unit- und Systemtests stehen
Die Begriffe werden in Teams nicht immer einheitlich verwendet. Ich halte deshalb eine einfache Abgrenzung für hilfreicher als eine dogmatische Definition: Entscheidend ist, wie viele reale Bestandteile am Test beteiligt sind und welche Grenze geprüft wird.
| Testart | Prüft hauptsächlich | Typisches Beispiel | Stärke |
|---|---|---|---|
| Unit-Test | Eine isolierte Funktion oder Klasse | Berechnung des Warenkorbwerts | Sehr schnell und präzise |
| Integrationstest | Das Zusammenspiel an einer oder mehreren Schnittstellen | Bestellung wird korrekt in der Datenbank gespeichert | Findet reale Integrationsfehler |
| Systemtest | Das vollständig integrierte System gegen Anforderungen | Kompletter Kaufprozess vom Login bis zur Versandbestätigung | Prüft das Verhalten aus Systemsicht |
| Akzeptanztest | Ob das System fachliche Erwartungen erfüllt | Ein Kunde kann eine Bestellung erfolgreich abschließen | Schafft Vertrauen bei Fachbereich und Auftraggeber |
Unit-Tests bleiben die schnellste Rückmeldung für reine Geschäftslogik. Sie können jedoch nicht zuverlässig zeigen, ob ein ORM die richtige Spalte anspricht, eine REST-Antwort korrekt gelesen wird oder eine Nachricht im erwarteten Format in einer Warteschlange landet. Dafür braucht es Tests an den echten technischen Grenzen.
Martin Fowler unterscheidet häufig zwischen schmalen und breiten Integrationstests. Schmale Varianten prüfen beispielsweise nur die Verbindung zu einer Datenbank oder einem externen Dienst. Breite Varianten spannen viele Services über ein gemeinsames Netzwerk auf und ähneln dadurch oft einem System- oder End-to-End-Test. Diese Unterscheidung ist nützlich, weil breite Tests zwar realistisch wirken, aber langsamer und schwieriger zu diagnostizieren sind.
Welche Integrationsarten sich bewährt haben
Top-down und bottom-up
Beim Top-down-Ansatz beginnt das Team mit den übergeordneten Komponenten und ersetzt noch nicht verfügbare Unterkomponenten durch Stubs. Ein Stub ist eine vereinfachte Ersatzkomponente, die vorher festgelegte Antworten liefert. Das eignet sich, wenn die zentrale Anwendungslogik früh geprüft werden soll.
Beim Bottom-up-Ansatz werden zuerst niedrigere Ebenen wie Datenzugriff, Adapter oder technische Services integriert. Höhere Module kommen später hinzu. Das ist besonders praktisch, wenn Datenbankzugriffe oder externe Schnittstellen die größten technischen Risiken darstellen.
Big Bang und schrittweise Integration
Bei der Big-Bang-Integration werden viele oder alle Komponenten gleichzeitig verbunden. Das klingt zunächst effizient, macht die Fehlersuche aber oft unnötig schwer. Wenn fünf Schnittstellen gleichzeitig beteiligt sind, lässt sich kaum erkennen, welche Grenze den Fehler verursacht.
Schrittweise Integration ist in der Praxis meist besser. Ich verbinde bevorzugt eine fachlich zusammenhängende Funktion nach der anderen, etwa Bestellung mit Datenbank, danach Bestellung mit Zahlungsdienst und anschließend Bestellung mit Versandservice. So bleibt der Fehlerbereich überschaubar.
Verträge und Test-Doubles
Ein Contract Test prüft, ob sich zwei Systeme an eine gemeinsam vereinbarte Schnittstelle halten. Der Vertrag beschreibt zum Beispiel Pflichtfelder, Datentypen und erlaubte Statuswerte. Test-Doubles wie Mocks, Stubs oder Fakes ersetzen reale Abhängigkeiten, wenn ein echter Dienst für den Test zu teuer, instabil oder nicht lokal verfügbar ist.
Solche Ersatzkomponenten sind hilfreich, dürfen aber die Realität nicht zu stark vereinfachen. Ein Mock, der immer eine perfekte Antwort liefert, schützt nicht vor einem fehlenden Feld, einer Zeitüberschreitung oder einem unerwarteten HTTP-Status. Deshalb kombiniere ich simulierte Tests mit einer kleineren Anzahl von Prüfungen gegen echte technische Komponenten.
So entsteht ein verlässlicher Testablauf
Ein guter Integrationstest beginnt nicht mit dem Testframework, sondern mit der Frage, wo Daten eine Systemgrenze überschreiten. Diese Grenzen werden anschließend nach Risiko und Geschäftswert priorisiert.
- Schnittstellen erfassen: Datenbanken, REST- oder GraphQL-APIs, Message Broker, Dateisysteme und externe Anbieter dokumentieren.
- kritische Szenarien auswählen: Erfolgsfälle, ungültige Daten, doppelte Nachrichten, Zeitüberschreitungen und Wiederholungen einplanen.
- Testumgebung festlegen: Abhängigkeiten möglichst lokal oder in einer isolierten Testumgebung betreiben.
- realistische Testdaten erzeugen: Daten sollten fachlich plausibel sein, dürfen aber keine produktiven Personen- oder Zahlungsdaten enthalten.
- klare Prüfungen definieren: Nicht nur HTTP 200 oder eine erfolgreiche Methode prüfen, sondern auch gespeicherte Daten, Statusänderungen und Nebenwirkungen.
- Tests in die Pipeline aufnehmen: Schnelle Prüfungen bei jedem Commit ausführen, umfangreichere Szenarien regelmäßig oder vor einem Release starten.
Bei einer Datenbankintegration reicht es zum Beispiel nicht, dass ein Repository ohne Ausnahme durchläuft. Ein belastbarer Test legt einen Datensatz an, liest ihn über den vorgesehenen Weg wieder aus und prüft Werte, Beziehungen und relevante Datenbankregeln. Wenn der Test nur den Rückgabewert eines Mocks kontrolliert, bleibt die eigentliche Datenbankgrenze ungetestet.
Für eine REST-API würde ich mindestens die Anfrage, Authentifizierung, Antwortstruktur und Fehlerfälle prüfen. Besonders wichtig sind Änderungen an JSON-Feldern, Datumsformaten und optionalen Werten. Genau solche kleinen Abweichungen verursachen in verteilten Systemen oft Fehler, die in lokalen Unit-Tests unsichtbar bleiben.
Welche Schnittstellen besondere Aufmerksamkeit brauchen
Nicht jede Integration birgt dasselbe Risiko. Die größten Probleme entstehen meist dort, wo Systeme unterschiedliche Annahmen über Format, Zeitpunkt oder Zuständigkeit haben.
Datenbanken
Tests gegen eine echte Datenbank finden Fehler bei Migrationen, Transaktionen, Indizes und Constraints. Eine In-Memory-Datenbank kann für einfache Prüfungen schnell sein, bildet aber nicht immer das Verhalten des produktiven Datenbanksystems ab. Für kritische Abfragen ist ein realer Datenbankdienst in einem isolierten Testcontainer oft die verlässlichere Wahl.
Externe APIs
Ein Produktivsystem sollte nicht als Testumgebung dienen. Tests können dort echte Bestellungen auslösen, Quoten verbrauchen oder sensible Protokolle erzeugen. Besser sind ein lokaler Fake, ein offizieller Sandbox-Dienst oder eine dedizierte Testinstanz mit kontrollierten Antworten.
Nachrichten und asynchrone Abläufe
Bei Queues und Events muss geprüft werden, ob Nachrichten korrekt veröffentlicht, konsumiert und bei Fehlern wiederholt werden. Ein Test sollte auch doppelte Zustellung und falsche Reihenfolgen berücksichtigen, denn genau diese Situationen treten in verteilten Systemen häufiger auf als im idealen Demoablauf.
Lesen Sie auch: Informationelle Selbstbestimmung - Ihr Leitfaden für IT-Projekte
Dateien und externe Ressourcen
Importe und Exporte scheitern oft an Zeichencodierung, Zeilenumbrüchen, Dateirechten oder großen Datenmengen. Ein realistischer Integrationstest verwendet deshalb mindestens eine gültige Datei, eine beschädigte Datei und einen Fall mit unerwarteten, aber syntaktisch zulässigen Werten.
Was häufig schiefgeht und wie man es besser macht
Der häufigste Fehler ist eine Test-Suite, die alles gleichzeitig prüft und bei einem Fehlschlag kaum Hinweise liefert. Solche Tests wirken umfassend, erzeugen aber lange Laufzeiten und unklare Fehlermeldungen. Kleine, gezielte Szenarien sind in der Regel wertvoller als ein einzelner riesiger Ablauf.
Ein zweites Problem sind Tests mit gemeinsamem Zustand. Wenn ein Test Daten hinterlässt, beeinflusst er den nächsten Test und führt zu zufälligen Fehlern. Jeder Test sollte seine Umgebung selbst vorbereiten und anschließend sauber zurücksetzen oder eine isolierte Datenbanktransaktion verwenden.
Auch übermäßig viele Mocks schaden. Sie machen Tests zwar schnell, können aber eine falsche Sicherheit erzeugen, wenn jede Abhängigkeit nur das erwartete Idealverhalten zeigt. Mein pragmatischer Maßstab lautet deshalb: Mocke Geschäftsabhängigkeiten gezielt, teste technische Grenzen real, sobald deren Verhalten für den Fehler entscheidend ist.
Ein weiterer Klassiker ist die Prüfung auf zu technische Details. Wenn ein Test jede interne Methode und jede Reihenfolge von Aufrufen kontrolliert, bricht er bei harmlosen Refactorings. Besser ist es, das beobachtbare Ergebnis zu prüfen, etwa den gespeicherten Bestellstatus oder das veröffentlichte Ereignis.
Wie Integrationstests in CI/CD sinnvoll bleiben
Integrationstests sollten in die Continuous-Integration-Pipeline passen, ohne jeden Commit unnötig auszubremsen. Schnelle, schmale Tests können bei jedem Push laufen. Breitere Tests mit mehreren Services gehören eher in einen separaten Pipeline-Schritt, in nächtliche Läufe oder an eine klare Release-Grenze.
| Pipeline-Stufe | Geeignete Tests | Praktisches Ziel |
|---|---|---|
| Pull Request | Schmale API-, Datenbank- und Vertragstests | Offensichtliche Integrationsfehler früh stoppen |
| Hauptbranch | Mehrere reale Services in isolierter Umgebung | Zusammenspiel nach dem Mergen prüfen |
| Vor dem Release | Breite System- und End-to-End-Szenarien | Kritische Geschäftsprozesse absichern |
| Nach der Bereitstellung | Smoke- und Health-Checks | Erreichbarkeit und Grundfunktionen verifizieren |
Die Laufzeit allein ist kein gutes Qualitätsmaß. Ein Test, der in 20 Sekunden läuft und unklar fehlschlägt, kann das Team stärker bremsen als ein stabiler Test mit 90 Sekunden Laufzeit. Entscheidend sind Reproduzierbarkeit, verständliche Logs und eine eindeutige Fehlerursache.
Der verlässlichste Test ist nah an der echten Systemgrenze
Integrationstests schließen eine Lücke, die weder isolierte Unit-Tests noch wenige große End-to-End-Tests vollständig abdecken. Sie zeigen, ob Komponenten Daten tatsächlich so austauschen, wie es die Anwendung und ihre externen Partner erwarten.
Ich würde deshalb nicht möglichst viele Integrationsprüfungen sammeln, sondern die wichtigsten Grenzen gezielt absichern. Eine kleine, stabile Suite für Datenbank, API, Nachrichten und kritische Fehlerfälle liefert meist mehr Wert als eine große Sammlung fragiler Tests, die niemand gern ausführt.
Wer Schnittstellen früh beschreibt, Testdaten sauber isoliert und reale Abhängigkeiten bewusst auswählt, erhält schnellere Rückmeldungen und deutlich weniger Überraschungen beim Release. Genau darin liegt der praktische Nutzen dieser Teststufe.