Eines meiner anfänglichen Bedenken von Spring Cloud Contract war, wie Sie die Verträge in Groovy definieren müssen, und in einem sehr Frühjahr spezifischen Groovy DSL. Es ist nicht etwas, das auf andere Technologien übertragbar wäre. Angenommen, der Dienst hat den Vertrag für zwei HTTP-Methoden definiert, die er verarbeiten kann. Schauen wir uns die Definition etwas genauer an. Unsere Vertragsfunktion nimmt eine Funktion als Parameter an. Es ist definiert als eine Funktion, die nur auf Instanzen von Contract.Builder aufgerufen werden kann, die `Unit` (`void` in Java) zurückgibt. Die Vertragsfunktion selbst gibt eine Instanz vom Typ Contract zurück, die aus dem Ausdruckstext abgeleitet werden kann, aber hier explizit zur Übersichtlichkeit deklariert wird. Damit dies funktioniert, erstellen wir eine neue Contract.Builder-Instanz. Als Nächstes werden wir die Funktion anwenden(builder) (oder aufrufen), die als Parameter für diese neue Instanz übergeben wurde. Schließlich geben wir das Ergebnis der Contract.Builder.build()-Funktion zurück: eine neu erstellte Contract-Instanz.
Die Verbraucherseite unseres CDC verbraucht Stubs, die von der Herstellerseite durch HTTP-Interaktion erzeugt werden, um den Vertrag aufrechtzuerhalten, so dass alle Änderungen auf der Herstellerseite den Vertrag brechen würden. Der vorherige Vertrag gibt an, dass jeder gültige POST-Test mit einem ID-Feld die in diesem Test definierte Antwort empfängt. Sie können Aufrufe von .jsonPath() verketten, um zusätzliche Übereinstimmungen hinzuzufügen. Wenn JSON Path nicht vertraut ist, kann Ihnen die JayWay-Dokumentation helfen, sich auf den Weg zu machen. Die WebTestClient-Version dieses Tests verfügt über einen ähnlichen statischen Hilfedienst, den Sie an derselben Stelle einfügen. Spring Cloud Contract bietet Plugins für Maven und Gradle, um Stubs aus Verträgen zu generieren. Dies sind WireMock Stubs wie das Obige Beispiel. Glücklicherweise unterstützt Spring Cloud Contract auch das Vertragsformat des Pakts. Um automatisch Tests aus einer pact-Datei zu generieren, müssen Sie die pact-Datei (die eine JSON-Datei ist) in den Ordner src/test/contracts legen und diese Abhängigkeiten zu Ihrem build.gradle hinzufügen: Als Produzent müssen Sie, wenn ein Vertrag definiert wird, die generierten Tests bestehen lassen, damit die Stubs veröffentlicht werden.
Es gibt Fälle, in denen Sie die Blockierung der Verbraucher aufheben möchten, damit sie die Stubs abrufen können, bevor Ihre Tests tatsächlich bestanden werden. In diesem Fall sollten Sie solche Verträge als in Bearbeitung festlegen. Weitere Informationen hierzu finden Sie im Abschnitt Verträge in Bearbeitung. Auf diese Weise werden Ihre Tests nicht generiert, aber die Stubs werden es tun. Aus dem Vertrag im vorherigen Beispiel sehen die generierten Tests und Stubs wie folgt aus: Dies funktioniert noch nicht. Damit dies funktioniert, verwenden wir eine Funktionalität, die in der Kotlin-Sprache enthalten ist, die Lambda es mit Empfängern genannt wird. Wir können eine Lambda-Funktion definieren, die für Instanzen eines bestimmten Typs funktioniert, d. h. wir können einen erwarteten Typ angeben, auf dem der Lambda ausgeführt werden soll. Im Lambda-Körper können wir dann Funktionen für die bereitgestellte Instanz aufrufen und/oder einige seiner Eigenschaften festlegen. Definieren wir die Contract()-Funktion – die der Einstiegspunkt für unsere DSL sein wird: Wir müssen die @Pact-Anmerkung verwenden und den Verbrauchernamen übergeben, für den der Vertrag definiert ist.
Innerhalb der kommentierten Methode können wir unseren GET-Vertrag definieren: Lassen Sie uns die Dinge aufschlüsseln, wie die Verträge in der Open API Specification definiert werden. Effektiv werden die Tests gegen den Vertrag durchgeführt. Im Moment hat der Hersteller keinen Implementierungscode, sondern nur den Servicevertrag in Form von Groovy DSL. Beachten Sie, dass der Vertrag DSL erlaubt, Matcher anstelle von statischen Inhalten anzugeben, so dass der in unserem Vertrag definierte Benutzername nicht “Arthur Dent” sein muss, sondern z. B. ein String sein kann.