Start / Seminare / Moderne API-Entwicklung mit REST, OpenAPI und Contract Testing
Modul
Provider Contracts mit Spring Cloud Contract
4 Kapitel in diesem Modul-Video · Laufzeit
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Provider Contracts mit Spring Cloud Contract
0:00 Im letzten Modul kam der Vertrag vom Consumer. Jetzt drehen wir die Richtung um. Spring Cloud Contract erlaubt beides, wird in der Praxis aber häufig so eingesetzt, dass der Provider aufschreibt, was er zusagt — und der Build sorgt dafür, dass er sich daran hält. Der Clou dabei ist, dass aus derselben Datei zwei Dinge entstehen: ein Test für den Provider und ein fertiger Stub für die Consumer.
0:23 Beide können damit nicht mehr auseinanderlaufen.
Provider Contracts mit Spring Cloud Contract
0:26 Drei Etappen. Zuerst die Verträge selbst: Wie sehen sie aus, in welchen Sprachen kann man sie schreiben, wo liegen sie. Dann die Mechanik des Builds — was das Plugin daraus erzeugt und wie ein Consumer die Stubs benutzt. Und zum Schluss die Frage, die Sie am ehesten mit ins eigene Haus nehmen: Pact oder Spring Cloud Contract, und woran diese Wahl tatsächlich hängt.
Verträge beschreiben
0:47 Fangen wir mit dem Artefakt an. Ein Vertrag ist hier eine Datei im Projekt — nicht etwas, das aus einem Testlauf herausfällt. Das ist der erste sichtbare Unterschied zu gestern. Das hat einen Vorteil und einen Preis: Der Vertrag lebt mit dem Dienst mit — aber er entsteht nicht automatisch aus dem, was ein Consumer tatsächlich braucht.
1:08 Die Dokumentation beschreibt den Anspruch so: testgetriebene Entwicklung auf die Ebene der Systemintegration heben. Das trifft es gut. Was bei TDD der Test für eine Methode ist, ist hier der Vertrag für eine Schnittstelle — er steht vor der Implementierung und beschreibt, was gelten soll. Der praktische Gewinn steckt im zweiten Satz: Aus derselben Datei entstehen Providertests und Consumer-Stubs.
1:31 Es gibt also keine Möglichkeit, dass der Stub etwas anderes behauptet als der Test prüft. Genau daran scheitern handgeschriebene Mocks. Vier Möglichkeiten, und die Wahl hängt an Ihrem Umfeld. Die Groovy DSL ist das ursprüngliche und ausdrucksstärkste Format — dort sind Matcher am elegantesten zu schreiben. YAML ist die pragmatische Wahl, wenn auf der Consumerseite niemand JVM-Erfahrung hat und trotzdem Verträge lesen soll.
1:58 Java und Kotlin lohnen sich, wenn der Vertrag im Projekt mitkompilieren soll, weil dann die Entwicklungsumgebung mithilft. Und die Ablage ist per Voreinstellung geregelt: unter src/test/resources/contracts. Achten Sie auf die Struktur statt auf die Syntax: oben die Anfrage, unten die Antwort, und in der Antwort ein Matcher statt eines festen Werts.
2:19 Das ist genau derselbe Gedanke wie gestern bei Pact — geprüft wird die Gestalt, nicht der konkrete Wert. Und die Fußnote nennt den eigentlichen Gewinn dieser wenigen Zeilen: Aus ihnen entsteht der Test, der Ihren Provider prüft, und der Stub, gegen den die Consumer entwickeln. Eine Quelle, zwei Ergebnisse, keine Möglichkeit zur Abweichung.
2:39 Der erste Punkt ist eine Ablagefrage mit Folgen: Verträge, die nicht mit dem Dienst versioniert sind, passen irgendwann nicht mehr zu ihm. Der zweite ist der Matcher-Fehler, den wir gestern schon hatten — feste Werte machen den Vertrag von Testdaten abhängig. Der dritte ist der peinlichste und wird vom generierten Test sofort aufgedeckt: Ein Vertrag beschreibt eine Antwort, die die Anwendung so nie liefert.
3:03 Und der vierte ist ein Organisationsthema, das man früh klären sollte — zwei Formate parallel, und niemand weiß, welches gilt.
Tests und Stubs erzeugen
3:11 Jetzt zur Mechanik. Der angenehme Teil an Spring Cloud Contract ist, dass Sie nach der Einrichtung wenig tun müssen — das Plugin erledigt die Arbeit im normalen Build. Das Angenehme daran ist, dass Sie nach der Einrichtung wenig tun müssen. Es passiert im ganz normalen Build, bei jedem Lauf. Zwei Ergebnisse entstehen im selben Lauf. Erstens Testklassen, die gegen Ihre laufende Anwendung prüfen — mit MockMvc als Voreinstellung, alternativ auch mit anderen Frameworks.
3:40 Zweitens die WireMock-Stubs, gepackt als Artefakt mit dem Klassifikator stubs. Dieser Klassifikator ist die Adresse, unter der Consumer sie später finden. Das Prinzip dahinter ist elegant: Der Stub geht denselben Weg wie jede andere Bibliothek — über Ihr Artefakt-Repository. Keine zusätzliche Infrastruktur, kein zusätzlicher Dienst.
4:02 Der zweite Schritt ist der einzige, der etwas Nachdenken verlangt: die Basisklasse. Sie stellt den Ausgangszustand her, gegen den die erzeugten Tests laufen — sie ist damit das Gegenstück zum Provider State bei Pact, nur eben als Java-Klasse. Der vierte Schritt enthält eine wichtige Absicherung: Das Stub-Artefakt entsteht nur bei grünem Lauf.
4:22 Ein Stub, der ein Verhalten verspricht, das die Anwendung nicht zeigt, kann also gar nicht erst veröffentlicht werden. Das ist die zentrale Zusicherung dieses Verfahrens. Für den Consumer ist der Aufwand erfreulich klein. Eine Annotation, darin die Koordinaten des Artefakts und ein Port — und im Test läuft ein Stub, der sich verhält wie der echte Dienst.
4:43 Beachten Sie das Pluszeichen in den Koordinaten: Damit nimmt der Consumer die jeweils neueste Version. Das ist bequem und zugleich der Punkt, an dem Sie eine Entscheidung treffen sollten, denn feste Versionen sind reproduzierbarer. Und der Unterschied zwischen LOCAL und REMOTE entscheidet, ob die Stubs aus dem lokalen oder dem entfernten Repository kommen.
5:04 Der zweite Punkt ist die Kehrseite fester Versionen: Ein Consumer, der eine Version festnagelt, bemerkt neue Stubs nie — und damit auch keine Änderung am Provider. Der dritte Punkt ist die Absicherung von eben, in ihrer verletzten Form: Stubs veröffentlichen, obwohl die Tests rot waren, hebelt das ganze Verfahren aus. Und der vierte ist derselbe Fehler wie bei generiertem Client-Code gestern: Erzeugte Testklassen ins Repository einchecken.
5:29 Sie driften dann von den Verträgen weg, aus denen sie stammen.
Den passenden Ansatz auswählen
5:34 Kommen wir zur Frage, die Sie mit nach Hause nehmen. Zwei Werkzeuge, ähnliches Ziel, unterschiedliche Wege — und eine Entscheidung, die weniger an Geschmack hängt, als man denkt. Ich möchte Ihnen die Entscheidung nicht abnehmen, sondern die Kriterien dafür geben. Denn welches Werkzeug passt, hängt vor allem an Ihren Consumern.
5:53 Wichtig ist zunächst eine Klarstellung: Spring Cloud Contract ist nicht auf producergetriebene Verträge festgelegt. Die Dokumentation beschreibt beide Richtungen — Verträge können vom Provider vorgegeben oder von den Consumern beigesteuert werden, dann sogar in einem eigenen Repository. Der Unterschied liegt also nicht im Werkzeug, sondern darin, wer die Erwartung formuliert und wo sie liegt. Das ist eine Organisationsentscheidung, keine technische.
6:19 Und sie sollte bewusst getroffen werden, nicht aus der Voreinstellung heraus entstehen. Zwei Zeilen entscheiden im Alltag. Die dritte: Bei Pact gibt es Bibliotheken für viele Sprachen, bei Spring Cloud Contract steht die JVM im Vordergrund — der Consumer bekommt allerdings einen WireMock-Stub, und der ist sprachneutral, weil er einfach ein HTTP-Server ist.
6:40 Und die vierte Zeile: Pact braucht einen Broker als eigenen Dienst, Spring Cloud Contract nutzt Ihr Artefakt-Repository oder Git. Wer keinen zusätzlichen Dienst betreiben will, findet das attraktiv — verliert aber die Matrix und damit can-i-deploy. Die erste Frage ist die praktisch wichtigste: Wo laufen Ihre Consumer? In unserem Beispiel ist der Provider Java und der Consumer TypeScript — genau die Konstellation, in der Pact seine Stärke ausspielt.
7:07 Der dritte Punkt ist der, den viele unterschätzen: Wollen Sie Freigaben an einer Matrix hängen? Das ist ein qualitativer Sprung gegenüber grünen Testläufen, und er ist bei Pact eingebaut. Und der vierte ist eine Kulturfrage: Verträge vorgeben oder Erwartungen einsammeln — beides funktioniert, aber nicht gleichzeitig. Der erste Punkt ist der Zustand, in den Organisationen geraten, wenn zwei Teams unabhängig entscheiden: Beide Werkzeuge laufen, und im Konfliktfall weiß niemand, welcher Vertrag gilt.
7:37 Der zweite ist der häufigste Entscheidungsfehler — die Wahl fällt nach Bekanntheit statt nach der Consumerlandschaft. Der vierte ist der ernüchterndste: Verträge werden eingeführt, aber die Freigabe hängt weiter am Gefühl. Dann haben Sie Werkzeugkosten ohne den eigentlichen Nutzen, denn der liegt in der automatisierten Entscheidung.
Übung
7:56 In der Übung machen Sie beides — und vergleichen anschließend. Das ist die einzige Art, diese Entscheidung ehrlich zu treffen: Man muss beide Wege einmal gegangen sein. Denn eine Werkzeugentscheidung, die nur auf Präsentationen beruht, hält der ersten Woche Praxis selten stand. Erst wer beide Wege einmal gegangen ist, kann sie ehrlich vergleichen.
8:17 Ihre Aufgabe ist, dieselbe Zusage, die Sie gestern als Pact formuliert haben, jetzt als Spring-Cloud-Contract-Vertrag zu beschreiben. Daraus soll ein laufender Providertest und ein Stub-Artefakt entstehen, und ein Consumer soll gegen diesen Stub laufen. Das eigentliche Ergebnis ist aber der dritte Teil: eine schriftliche, begründete Entscheidung für Ihr eigenes Umfeld.
8:39 Nicht welches Werkzeug besser ist — sondern welches zu Ihren Consumern passt. Schritt drei ist der lehrreichste: Sehen Sie sich den erzeugten Test wirklich an. Er zeigt, was das Plugin aus Ihrem Vertrag gemacht hat, und macht das Verfahren nachvollziehbar. Schritt fünf ist die eigentliche Aufgabe und braucht die meiste Zeit.
8:58 Nehmen Sie dafür Ihre reale Consumerlandschaft — welche Sprachen, wie viele Teams, wie werden Deployments heute freigegeben. Die Antwort darauf entscheidet, und sie ist in jedem Haus anders. Der erste Punkt ist die typische Abkürzung bei dieser Übung: Die Bewertung endet bei Geschmacksfragen — YAML gegen Groovy, Annotation gegen Broker. Das sind Oberflächen.
9:20 Die Entscheidung fällt bei den Consumern. Der zweite Punkt ist ein Einrichtungsärgernis, das Sie erleben werden, wenn zwei Gruppen denselben Port nehmen. Und der dritte ist der inhaltliche Fehler, der auch bei Pact lauert: Ein Vertrag, der Geschäftslogik prüft, gehört auf eine andere Teststufe — die aus Modul 10.
Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →