Added a Spring-based consumer
authorKai Moritz <kai@juplo.de>
Sat, 21 May 2022 10:47:16 +0000 (12:47 +0200)
committerKai Moritz <kai@juplo.de>
Fri, 3 Jun 2022 11:29:14 +0000 (13:29 +0200)
* Goal: re-stage the contract with Spring for educational purposes
* Generates a totally different contract for now...
* Is copied from the code-example for the PactDslJsonBody DSL
* See: https://docs.pact.io/implementation_guides/jvm/consumer#building-json-bodies-with-pactdsljsonbody-dsl[example-code]
* Added Maven-Builddirectory to .gitignore
* Added the generated JSON for comparison

.gitignore
spring-consumer/pom.xml [new file with mode: 0644]
spring-consumer/src/main/java/de/juplo/demos/pact/Application.java [new file with mode: 0644]
spring-consumer/src/test/java/de/juplo/demos/pact/ApplicationTests.java [new file with mode: 0644]
spring-consumer/src/test/java/de/juplo/demos/pact/ContractTest.java [new file with mode: 0644]
spring-consumer/target/pacts/SpringConsumer-Siren Order Provider.json [new file with mode: 0644]

index 3c2a5eb..0d1ebd5 100644 (file)
@@ -1,6 +1,7 @@
 .gradle
 build/
 node_modules/
+target/
 
 # Ignore Gradle GUI config
 gradle-app.setting
diff --git a/spring-consumer/pom.xml b/spring-consumer/pom.xml
new file mode 100644 (file)
index 0000000..23844a2
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.springframework.boot</groupId>
+               <artifactId>spring-boot-starter-parent</artifactId>
+               <version>2.7.0</version>
+               <relativePath/> <!-- lookup parent from repository -->
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <groupId>de.juplo.demos.pact</groupId>
+       <artifactId>siren-consumer</artifactId>
+       <version>1.0.0-SNAPSHOT</version>
+
+       <properties>
+               <java.version>11</java.version>
+               <pact.version>4.2.2</pact.version>
+       </properties>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-web</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.projectlombok</groupId>
+                       <artifactId>lombok</artifactId>
+                       <optional>true</optional>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-test</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>au.com.dius.pact.consumer</groupId>
+                       <artifactId>junit5</artifactId>
+                       <version>${pact.version}</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               <artifactId>spring-boot-maven-plugin</artifactId>
+                               <configuration>
+                                       <excludes>
+                                               <exclude>
+                                                       <groupId>org.projectlombok</groupId>
+                                                       <artifactId>lombok</artifactId>
+                                               </exclude>
+                                       </excludes>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <artifactId>maven-failsafe-plugin</artifactId>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
diff --git a/spring-consumer/src/main/java/de/juplo/demos/pact/Application.java b/spring-consumer/src/main/java/de/juplo/demos/pact/Application.java
new file mode 100644 (file)
index 0000000..5dccaa0
--- /dev/null
@@ -0,0 +1,14 @@
+package de.juplo.demos.pact;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application
+{
+
+       public static void main(String[] args) {
+               SpringApplication.run(Application.class, args);
+       }
+
+}
diff --git a/spring-consumer/src/test/java/de/juplo/demos/pact/ApplicationTests.java b/spring-consumer/src/test/java/de/juplo/demos/pact/ApplicationTests.java
new file mode 100644 (file)
index 0000000..7c96248
--- /dev/null
@@ -0,0 +1,14 @@
+package de.juplo.demos.pact;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ApplicationTests
+{
+
+       @Test
+       void contextLoads() {
+       }
+
+}
diff --git a/spring-consumer/src/test/java/de/juplo/demos/pact/ContractTest.java b/spring-consumer/src/test/java/de/juplo/demos/pact/ContractTest.java
new file mode 100644 (file)
index 0000000..d7358d8
--- /dev/null
@@ -0,0 +1,62 @@
+package de.juplo.demos.pact;
+
+import au.com.dius.pact.consumer.MockServer;
+import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
+import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
+import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
+import au.com.dius.pact.consumer.junit5.PactTestFor;
+import au.com.dius.pact.core.model.RequestResponsePact;
+import au.com.dius.pact.core.model.annotations.Pact;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.fail;
+
+
+@ExtendWith(PactConsumerTestExt.class)
+@PactTestFor(providerName = "Siren Order Provider")
+public class ContractTest
+{
+  @Pact(consumer="SpringConsumer")
+  public RequestResponsePact getOrders(PactDslWithProvider builder)
+  {
+    PactDslJsonBody body = new PactDslJsonBody()
+        .stringType("name")
+        .booleanType("happy")
+        .hexValue("hexCode")
+        .id()
+        .ipAddress("localAddress")
+        .numberValue("age", 100);
+    return builder
+          .uponReceiving("get all orders")
+            .path("/orders")
+            .method("GET")
+          .willRespondWith()
+            .status(200)
+            .headers(Map.of("Content-Type", "application/vnd.siren+json"))
+            .body(body)
+        .toPact();
+  }
+
+  @Test
+  @PactTestFor(pactMethod = "getOrders")
+  public void testGetExistingUserByEmail(MockServer mockServer)
+  {
+    RestTemplate restTemplate =
+        new RestTemplateBuilder()
+            .rootUri(mockServer.getUrl())
+            .build();
+    try
+    {
+      restTemplate.getForEntity("/orders", String.class);
+    }
+    catch (Exception e)
+    {
+      fail("Unexpected exception", e);
+    }
+  }
+}
diff --git a/spring-consumer/target/pacts/SpringConsumer-Siren Order Provider.json b/spring-consumer/target/pacts/SpringConsumer-Siren Order Provider.json
new file mode 100644 (file)
index 0000000..3d6d034
--- /dev/null
@@ -0,0 +1,102 @@
+{
+  "consumer": {
+    "name": "SpringConsumer"
+  },
+  "interactions": [
+    {
+      "description": "get all orders",
+      "request": {
+        "method": "GET",
+        "path": "/orders"
+      },
+      "response": {
+        "body": {
+          "age": 100,
+          "happy": true,
+          "hexCode": "1234a",
+          "id": 1234567890,
+          "localAddress": "127.0.0.1",
+          "name": "string"
+        },
+        "generators": {
+          "body": {
+            "$.hexCode": {
+              "digits": 10,
+              "type": "RandomHexadecimal"
+            },
+            "$.id": {
+              "max": 2147483647,
+              "min": 0,
+              "type": "RandomInt"
+            },
+            "$.name": {
+              "size": 20,
+              "type": "RandomString"
+            }
+          }
+        },
+        "headers": {
+          "Content-Type": "application/vnd.siren+json"
+        },
+        "matchingRules": {
+          "body": {
+            "$.happy": {
+              "combine": "AND",
+              "matchers": [
+                {
+                  "match": "type"
+                }
+              ]
+            },
+            "$.hexCode": {
+              "combine": "AND",
+              "matchers": [
+                {
+                  "match": "regex",
+                  "regex": "[0-9a-fA-F]+"
+                }
+              ]
+            },
+            "$.id": {
+              "combine": "AND",
+              "matchers": [
+                {
+                  "match": "type"
+                }
+              ]
+            },
+            "$.localAddress": {
+              "combine": "AND",
+              "matchers": [
+                {
+                  "match": "regex",
+                  "regex": "(\\d{1,3}\\.)+\\d{1,3}"
+                }
+              ]
+            },
+            "$.name": {
+              "combine": "AND",
+              "matchers": [
+                {
+                  "match": "type"
+                }
+              ]
+            }
+          }
+        },
+        "status": 200
+      }
+    }
+  ],
+  "metadata": {
+    "pact-jvm": {
+      "version": "4.2.2"
+    },
+    "pactSpecification": {
+      "version": "3.0.0"
+    }
+  },
+  "provider": {
+    "name": "Siren Order Provider"
+  }
+}