diff --git a/order-backend/src/main/java/auftragsverwaltung/infrastructure/ProductServiceImpl.java b/order-backend/src/main/java/auftragsverwaltung/infrastructure/ProductServiceImpl.java index e989646..6e09194 100644 --- a/order-backend/src/main/java/auftragsverwaltung/infrastructure/ProductServiceImpl.java +++ b/order-backend/src/main/java/auftragsverwaltung/infrastructure/ProductServiceImpl.java @@ -19,7 +19,7 @@ public ProductServiceImpl(RestTemplate restTemplate, @Value("${product.api.base- @Override public ProductDTO getProductById(Integer id) { - String url = baseUrl + "/products/{id}"; + String url = baseUrl + "/product-api/products/{id}"; return restTemplate.getForObject(url, ProductDTO.class, id); } } diff --git a/order-backend/src/test/java/auftragsverwaltung/contract/ProductConsumerPactTest.java b/order-backend/src/test/java/auftragsverwaltung/contract/ProductConsumerPactTest.java index 6148d7a..eac371b 100644 --- a/order-backend/src/test/java/auftragsverwaltung/contract/ProductConsumerPactTest.java +++ b/order-backend/src/test/java/auftragsverwaltung/contract/ProductConsumerPactTest.java @@ -8,6 +8,7 @@ import au.com.dius.pact.core.model.PactSpecVersion; import au.com.dius.pact.core.model.RequestResponsePact; import au.com.dius.pact.core.model.annotations.Pact; +import au.com.dius.pact.core.model.annotations.PactDirectory; import auftragsverwaltung.infrastructure.ProductDTO; import auftragsverwaltung.infrastructure.ProductServiceImpl; import org.junit.jupiter.api.Test; @@ -22,20 +23,22 @@ @ExtendWith(PactConsumerTestExt.class) @PactTestFor(providerName = "product-backend", pactVersion = PactSpecVersion.V3) +@PactDirectory("../pacts") class ProductConsumerPactTest { @Pact(consumer = "order-backend", provider = "product-backend") public RequestResponsePact getProduct_ok(PactDslWithProvider builder) { + Integer anyId = 1; PactDslJsonBody body = new PactDslJsonBody() - .numberType("id", 1) + .numberType("id", anyId) .stringType("name", "TestProduct") .numberType("price", 19.99) .stringMatcher("currency", "EUR|USD"); return builder - .given("product 1 exists") - .uponReceiving("GET /products/1") - .path("/products/1") + .given("product exists", Map.of("id", anyId)) + .uponReceiving("GET ein Product das existiert") + .pathFromProviderState("/product-api/products/${id}", "/product-api/products/%d".formatted(anyId)) .method("GET") .willRespondWith() .status(200) @@ -46,10 +49,11 @@ public RequestResponsePact getProduct_ok(PactDslWithProvider builder) { @Pact(consumer = "order-backend", provider = "product-backend") public RequestResponsePact getProduct_notFound(PactDslWithProvider builder) { + Integer notFoundId = 999; return builder - .given("product 999 not found") - .uponReceiving("GET /products/999") - .path("/products/999") + .given("product not found") + .uponReceiving("GET eine Produktnummer die nicht existiert") + .pathFromProviderState("/product-api/products/${notFoundId}", "/product-api/products/%d".formatted(notFoundId)) .method("GET") .willRespondWith() .status(404) diff --git a/pacts/order-backend-product-backend.json b/pacts/order-backend-product-backend.json new file mode 100644 index 0000000..6a794c6 --- /dev/null +++ b/pacts/order-backend-product-backend.json @@ -0,0 +1,119 @@ +{ + "consumer": { + "name": "order-backend" + }, + "interactions": [ + { + "description": "GET ein Product das existiert", + "providerStates": [ + { + "name": "product exists", + "params": { + "id": 1 + } + } + ], + "request": { + "generators": { + "path": { + "dataType": "STRING", + "expression": "/product-api/products/${id}", + "type": "ProviderState" + } + }, + "method": "GET", + "path": "/product-api/products/1" + }, + "response": { + "body": { + "currency": "EUR", + "id": 1, + "name": "TestProduct", + "price": 19.99 + }, + "generators": { + "body": { + "$.currency": { + "regex": "EUR|USD", + "type": "Regex" + } + } + }, + "headers": { + "Content-Type": "application/json" + }, + "matchingRules": { + "body": { + "$.currency": { + "combine": "AND", + "matchers": [ + { + "match": "regex", + "regex": "EUR|USD" + } + ] + }, + "$.id": { + "combine": "AND", + "matchers": [ + { + "match": "number" + } + ] + }, + "$.name": { + "combine": "AND", + "matchers": [ + { + "match": "type" + } + ] + }, + "$.price": { + "combine": "AND", + "matchers": [ + { + "match": "number" + } + ] + } + } + }, + "status": 200 + } + }, + { + "description": "GET eine Produktnummer die nicht existiert", + "providerStates": [ + { + "name": "product not found" + } + ], + "request": { + "generators": { + "path": { + "dataType": "STRING", + "expression": "/product-api/products/${notFoundId}", + "type": "ProviderState" + } + }, + "method": "GET", + "path": "/product-api/products/999" + }, + "response": { + "status": 404 + } + } + ], + "metadata": { + "pact-jvm": { + "version": "4.6.17" + }, + "pactSpecification": { + "version": "3.0.0" + } + }, + "provider": { + "name": "product-backend" + } +} diff --git a/pom.xml b/pom.xml index 4122983..1b88660 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 3.5.6 21 - 4.6.11 + 4.6.17 diff --git a/product-backend/src/test/java/auftragsverwaltung/provider/PactProviderVerificationTest.java b/product-backend/src/test/java/auftragsverwaltung/provider/PactProviderVerificationTest.java index 22d1125..f52955a 100644 --- a/product-backend/src/test/java/auftragsverwaltung/provider/PactProviderVerificationTest.java +++ b/product-backend/src/test/java/auftragsverwaltung/provider/PactProviderVerificationTest.java @@ -20,7 +20,7 @@ import produktkatalog.infrastructure.ProductService; import java.math.BigDecimal; -import java.math.BigInteger; +import java.util.Map; import java.util.Optional; import static org.mockito.Mockito.when; @@ -28,7 +28,7 @@ @Provider("product-backend") @Consumer("order-backend") -@PactFolder("../order-backend/target/pacts") +@PactFolder("../pacts") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = ProductApp.class) @ExtendWith(PactVerificationSpring6Provider.class) class PactProviderVerificationTest { @@ -41,18 +41,20 @@ class PactProviderVerificationTest { @BeforeEach void setup(@NotNull PactVerificationContext ctx) { - ctx.setTarget(new HttpTestTarget("localhost", port, "/product-api")); + ctx.setTarget(new HttpTestTarget("localhost", port)); } - @State("product 1 exists") - void setupUpProductExists() { - when(productService.getProductById(1)) - .thenReturn(Optional.of(new Product(1, "TestProduct", new BigDecimal("19.99"), EUR))); + @State("product exists") + void setupUpProductExists(Map params) { + Integer id = Integer.valueOf(params.getOrDefault("id", 1).toString()); + when(productService.getProductById(id)) + .thenReturn(Optional.of(new Product(id, "TestProduct", new BigDecimal("19.99"), EUR))); } - @State("product 999 not found") - void setUpProductNotFound() { - when(productService.getProductById(999)) + @State("product not found") + void setUpProductNotFound(Map params) { + Integer id = Integer.valueOf(params.getOrDefault("id", 1).toString()); + when(productService.getProductById(id)) .thenReturn(Optional.empty()); } @@ -61,14 +63,4 @@ void setUpProductNotFound() { void verify(PactVerificationContext ctx) { ctx.verifyInteraction(); } - - - private static Integer asInt(Object value) { - if (value instanceof Integer i) return i; - if (value instanceof Long l) return l.intValue(); - if (value instanceof BigInteger bi) return bi.intValue(); - if (value instanceof Number n) return n.intValue(); - return Integer.parseInt(String.valueOf(value)); - } - } diff --git a/product-backend/src/test/resources/pacts/order-backend-product-backend.json b/product-backend/src/test/resources/pacts/order-backend-product-backend.json deleted file mode 100644 index 1fe8d25..0000000 --- a/product-backend/src/test/resources/pacts/order-backend-product-backend.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "consumer": { - "name": "order-backend" - }, - "interactions": [ - { - "description": "GET /product-api/products/1", - "providerStates": [ - { - "name": "product with id 1 exists" - } - ], - "request": { - "method": "GET", - "path": "/product-api/products/1" - }, - "response": { - "body": { - "currency": "EUR", - "id": 1, - "name": "TestProduct", - "price": 19.99 - }, - "headers": { - "Content-Type": "application/json" - }, - "status": 200 - } - } - ], - "metadata": { - "pact-jvm": { - "version": "4.6.11" - }, - "pactSpecification": { - "version": "3.0.0" - } - }, - "provider": { - "name": "product-backend" - } -}