Skip to content

Commit cfd4eda

Browse files
committed
fixme: DeliveryAddressRepositoryTest
1 parent 5df50f8 commit cfd4eda

3 files changed

Lines changed: 42 additions & 278 deletions

File tree

.github/workflows/build.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
cache: maven
1818

1919
- name: Build customer-service
20-
run: mvn clean package -f customer-service/pom.xml
20+
run: mvn clean package -f customer-service/pom.xml -DskipTests
2121

2222
- name: Build billing-service
2323
run: mvn clean package -f billing-service/pom.xml

README.md

Lines changed: 38 additions & 249 deletions
Original file line numberDiff line numberDiff line change
@@ -24,252 +24,41 @@ Schaue im Jenkins nach, ob alle Pipelines durchgelaufen sind.
2424
Wenn die vier Services deployt sind, kann die Swagger-UI des Customer Services auf dem Testsystem
2525
über folgende URL erreicht werden: [Customer-Service](http://localhost:8281)
2626

27-
## Übung 1 - Verwendung des Pact-Brokers
28-
29-
Der Pact Broker ist bisher (außer eines Sample Contracts) leer.
30-
31-
Wir wollen jetzt, dass die Services ihre Contracts via Pact austauschen.
32-
Dazu muss in allen vier Services der Branch `pact-broker`
33-
in den Branch `develop` gemergt werden.
34-
Gehe auf den Git-Server und erstelle zunächst im `customer-service`
35-
einen Pull-Request mit dem Base-Branch `develop`
36-
und dem Vergleichs-Branch `pact-broker` und führe diese dann zusammen.
37-
Die Jenkins-Pipeline sollte nun automatisch anfangen zu bauen
38-
und den neuen Stand des Customer Services auf das Testsystem deployen.
39-
40-
Wenn das geschehen ist, kannst du im Pact-Broker sehen,
41-
dass vom Customer Service zwei Contracts hochgeladen wurden,
42-
einer für den Billing Service und einer für den Delivery Service.
43-
Beide Contracts sind allerdings noch nicht verifiziert.
44-
45-
Wir mergen nun im Billing Service den Branch `pact-broker` in den Branch `develop`.
46-
Dazu erstellen wir wieder, wie oben beschrieben, einen Pull-Request
47-
und führen ihn zusammen.
48-
49-
Nachdem wir beobachtet haben, dass der Billing Service gebaut
50-
und deployt wurde, können wir im Pact Broker sehen,
51-
dass der Billing Service den Contract des Customer Services verifiziert hat.
52-
53-
Wir mergen nun analog den Delivery Service und beobachten auch hier,
54-
dass er den Contract verifiziert.
55-
56-
Eine weitere Beobachtung wird sein,
57-
dass der Delivery Service einen weiteren Contract hochgeladen hat,
58-
nämlich für den Address Validation Service.
59-
60-
Zu guter Letzt mergen wir also den Branch `pact-broker`
61-
auch im Address Validation Service in den Branch `develop`
62-
und beobachten auch hier die Verifizierung.
63-
64-
## Übung 2 - Nur deployen, wenn der Branch verifiziert ist.
65-
66-
Es wäre wünschenswert, dass ein Service nur deployt wird,
67-
wenn seine Contracts auch von den jeweiligen Providern verifiziert wurden.
68-
Um das zu erreichen, müssen wir die Pipelines so umbauen,
69-
dass die Consumer die Pipelines der Provider immer dann antriggern,
70-
wenn sie einen neuen Contract hochgeladen haben.
71-
72-
Zunächst müssen wir allerdings die Provider-Pipelines so umbauen,
73-
dass sie dann auch nur die Contracts verifizieren (und nicht selber deployen).
74-
Dazu mergen wir zunächst im Address Validation Service und im Billing Service
75-
jeweils den Branch `pipeline` in den Branch `develop`.
76-
77-
Ist das geschehen (und das jeweilige Build erfolgreich durchgelaufen),
78-
können wir zunächst im Delivery Service den Branch `pipeline` in den Branch `develop` mergen.
79-
Danach können wir beobachten, wie der Build des Delivery Services
80-
den Build des Address Validation Services anstößt, dieser nur bis zur Phase Test baut
81-
(und den Contract verifiziert) und dann der Build des Delivery Services fortgesetzt wird.
82-
83-
Anschließend können wir dasselbe im Customer Service beobachten,
84-
wenn wir auch hier den Branch `pipeline` nach `develop` mergen.
85-
Hier lässt sich beobachten, dass sowohl der Build des Billing Services
86-
als auch der Build des Delivery Services angestoßen wird.
87-
88-
## Übung 3 - Verifizieren der Contracts von unterschiedlichen Stages
89-
90-
Um sicherzustellen, dass alle Versionen einer Stage zusammenpassen,
91-
gibt es in Pact das Konzept der Branches und Environments.
92-
93-
Sobald ein Service in einer Version auf einer Stage deployt worden ist,
94-
kann diese Version im Pact-Broker mit Tags für Branch und Environment (Stage) versehen werden.
95-
96-
Wir können das sehen, indem wir sowohl im Address Validation Service
97-
als auch im Billing Service jeweils den Branch `pact-tags` in den Branch `develop` mergen.
98-
Nach erfolgreichem Deployment sind die jeweiligen Versionen im Pact Broker jeweils mit
99-
Branch `develop` und Environment `test` getaggt.
100-
101-
Wenn wir nun im Delivery Service den Branch `pact-tags` in `develop` mergen,
102-
wird der Delivery Service im Pact Broker für den Contract mit dem Address Validation
103-
Service mit dem Branch `develop` getaggt. In der Pipeline können wir beobachten, dass
104-
versucht wird, die Pipeline des Address Validation Services zu starten. Wir merken jedoch,
105-
dass sich da nichts tut. Das Problem ist, dass per Default in unserer Jenkins-Instanz
106-
nur ein Build-Prozessor aktiv ist. Daher müssen wir in den Systemeinstellungen die Anzahl
107-
der Build-Prozessoren auf 2 hochsetzen. Anschließend können wir beobachten, dass die Pipeline
108-
des Address Validation Services parallel zu starten beginnt. Der Service verwendet beim
109-
Verifizieren des Contracts die Version, die auch auf der Stage deployt ist, auf die der
110-
Delivery Service deployen möchte (in diesem Fall die Test-Stage). Nachdem der Address Validation
111-
Service den Contract verifiziert hat, darf der Delivery Services deployen und taggt seine Seite
112-
des Contracts mit dem Environment `test`.
113-
114-
Dasselbe können wir erneut beim Customer Service beobachten,
115-
wenn wir auch hier den Branch `pact-tags` in den Branch `develop` mergen.
116-
117-
## Übung 4 - Unabhängige Pipelines
118-
119-
Bisher ist es so, dass die Abhängigkeiten zwischen den Pipelines explizit
120-
im `Jenkinsfile` eingetragen sind.
121-
In der Praxis ist das nicht immer möglich.
122-
Wenn Services von unterschiedlichen Teams umgesetzt werden und eventuell
123-
sogar auf unterschiedlichen Build-Servern laufen,
124-
werden andere Mechanismen benötigt, um die Verifikation von Contracts anzustoßen.
125-
126-
Der Pact Broker bietet hierzu die Möglichkeit,
127-
zwei Arten von Webhooks zu registrieren.
128-
Einerseits kann man einen Webhook registrieren,
129-
der aufgerufen wird, wenn ein Contract hochgeladen wird.
130-
Andererseits kann man einen Webhook registrieren,
131-
der aufgerufen wird, wenn ein Contract verifiziert
132-
und das Ergebnis hochgeladen wurde.
133-
Ersteren werden wir verwenden, um die Verifikation anzustoßen.
134-
135-
Wir können die Webhooks registrieren, indem wir im Pact-Broker rechts oben
136-
auf den `API Browser` gehen.
137-
Dort suchen wir die Ressource `pb:webhooks` und klicken auf `Perform non-GET request`.
138-
Das ist das gelb unterlegte `!`.
139-
140-
Insgesamt wollen wir fünf Webhooks anlegen:
141-
zunächst einmal drei zum Antriggern der Verifikation
142-
(nämlich für den Billing Service, den Delivery Service und den Address Validation Service).
143-
Dazu führen wir drei POST-Requests mit den folgenden Bodys aus:
144-
145-
```
146-
{
147-
"provider": {
148-
"name": "billing-service"
149-
},
150-
"events": [{
151-
"name": "contract_requiring_verification_published"
152-
}],
153-
"request": {
154-
"method": "GET",
155-
"url": "http://jenkins:8080/generic-webhook-trigger/invoke?token=billing-service&branch=${pactbroker.consumerVersionBranch}&verifyPacts=true",
156-
"headers": {
157-
},
158-
"body": {
159-
"event_type": "contract_requiring_verification_published",
160-
"client_payload": {
161-
"pact_url": "${pactbroker.pactUrl}",
162-
"sha": "${pactbroker.providerVersionNumber}",
163-
"branch": "${pactbroker.providerVersionBranch}",
164-
"message": "Verify changed pact for ${pactbroker.consumerName} version ${pactbroker.consumerVersionNumber} branch ${pactbroker.consumerVersionBranch} by ${pactbroker.providerVersionNumber} (${pactbroker.providerVersionDescriptions})"
165-
}
166-
}
167-
}
168-
}
169-
```
170-
171-
```
172-
{
173-
"provider": {
174-
"name": "delivery-service"
175-
},
176-
"events": [{
177-
"name": "contract_requiring_verification_published"
178-
}],
179-
"request": {
180-
"method": "GET",
181-
"url": "http://jenkins:8080/generic-webhook-trigger/invoke?token=delivery-service&branch=${pactbroker.consumerVersionBranch}&verifyPacts=true",
182-
"headers": {
183-
},
184-
"body": {
185-
"event_type": "contract_requiring_verification_published",
186-
"client_payload": {
187-
"pact_url": "${pactbroker.pactUrl}",
188-
"sha": "${pactbroker.providerVersionNumber}",
189-
"branch": "${pactbroker.providerVersionBranch}",
190-
"message": "Verify changed pact for ${pactbroker.consumerName} version ${pactbroker.consumerVersionNumber} branch ${pactbroker.consumerVersionBranch} by ${pactbroker.providerVersionNumber} (${pactbroker.providerVersionDescriptions})"
191-
}
192-
}
193-
}
194-
}
195-
```
196-
197-
```
198-
{
199-
"provider": {
200-
"name": "address-validation-service"
201-
},
202-
"events": [{
203-
"name": "contract_requiring_verification_published"
204-
}],
205-
"request": {
206-
"method": "GET",
207-
"url": "http://jenkins:8080/generic-webhook-trigger/invoke?token=address-validation-service&branch=${pactbroker.consumerVersionBranch}&verifyPacts=true",
208-
"headers": {
209-
},
210-
"body": {
211-
"event_type": "contract_requiring_verification_published",
212-
"client_payload": {
213-
"pact_url": "${pactbroker.pactUrl}",
214-
"sha": "${pactbroker.providerVersionNumber}",
215-
"branch": "${pactbroker.providerVersionBranch}",
216-
"message": "Verify changed pact for ${pactbroker.consumerName} version ${pactbroker.consumerVersionNumber} branch ${pactbroker.consumerVersionBranch} by ${pactbroker.providerVersionNumber} (${pactbroker.providerVersionDescriptions})"
217-
}
218-
}
219-
}
220-
}
221-
```
222-
223-
Außerdem legen wir mit weiteren POST-Requests noch zwei Webhooks an, die getriggert werden, wenn eine Verifikation erfolgreich war
224-
und der Service auf die Stage deployen kann. Diese brauchen wir für den Customer Service und den Delivery Service.
225-
226-
```
227-
{
228-
"consumer": {
229-
"name": "customer-service"
230-
},
231-
"events": [{
232-
"name": "provider_verification_published"
233-
}],
234-
"request": {
235-
"method": "GET",
236-
"url": "http://jenkins:8080/generic-webhook-trigger/invoke?token=customer-service&branch=${pactbroker.consumerVersionBranch}&deployOnly=true&deploymentVersion=${pactbroker.consumerVersionNumber}",
237-
"headers": {
238-
}
239-
}
240-
}
241-
```
242-
243-
```
244-
{
245-
"consumer": {
246-
"name": "delivery-service"
247-
},
248-
"events": [{
249-
"name": "provider_verification_published"
250-
}],
251-
"request": {
252-
"method": "GET",
253-
"url": "http://jenkins:8080/generic-webhook-trigger/invoke?token=delivery-service&branch=${pactbroker.consumerVersionBranch}&deployOnly=true&deploymentVersion=${pactbroker.consumerVersionNumber}",
254-
"headers": {
255-
}
256-
}
257-
}
258-
```
259-
260-
Wenn wir alle Webhooks angelegt haben, können wir das Ganze testen,
261-
indem wir jeweils die Branches `webhook` in den Branch `main` mergen.
262-
263-
Zunächst tun wir das für den Billing Service und den Address Validation Service und warten,
264-
bis diese auf dem Produktivsystem deployt sind.
265-
266-
Danach mergen wir den Branch im Delivery Service. Nun können wir beobachten,
267-
wie der Delivery Service gebaut und gepusht wird, aber noch nicht deployt wird,
268-
weil sein hochgeladener Contract noch nicht für die Production Stage verifiziert ist.
269-
Das Hochladen des Contracts hat aber bereits den Address Validation Service angestoßen,
270-
der die Verifikation vornimmt. Sobald der Address Validation Service den Contract verifiziert hat,
271-
wird über den Webhook wieder der Delivery Service angestoßen, der jetzt nur noch deployt.
272-
273-
Wenn wir im Customer Service auch den Branch `webhook` nach `main` mergen,
274-
können wir hier dasselbe beobachten, nur dass der Customer Service die Verifikation
275-
in Billing Service und Delivery Service anstößst und auch auf beide Verifikationen wartet.
27+
## Übung: Consumer-Driven Contract Tests schreiben
28+
29+
Im `customer-service` liegt bereits eine Testklasse `DeliveryAddressRepositoryTest`,
30+
die Consumer-Driven Contract Tests mit Pact für den Delivery Service definiert.
31+
Die Tests sind jedoch noch unvollständig: Requests und Responses enthalten noch keine Bodies,
32+
und ein Statuscode ist falsch gesetzt.
33+
34+
Vervollständige die Pact-Consumer-Tests in der Klasse
35+
`customer-service/src/test/java/de/openknowledge/sample/address/domain/DeliveryAddressRepositoryTest.java`:
36+
37+
1. **`getMax`** – Füge einen Response-Body hinzu, der die Lieferadresse von Max Mustermann beschreibt:
38+
- `recipient`: `"Max Mustermann"`
39+
- `city`: `"26122 Oldenburg"`
40+
- `street.name`: `"Poststr."`
41+
- `street.number`: `"1"`
42+
43+
2. **`dontGetMissing`** – Korrigiere den Statuscode: Eine nicht gefundene Adresse sollte `404` (nicht `204`) zurückliefern.
44+
45+
3. **`updateMax`** – Füge einen Request-Body hinzu, der die neue Lieferadresse beschreibt:
46+
- `recipient`: `"Erika Mustermann"`
47+
- `city`: `"45127 Essen"`
48+
- `street.name`: `"II. Hagen"`
49+
- `street.number`: `"7"`
50+
51+
4. **`dontUpdateSherlock`** – Vervollständige Request und Response:
52+
- Füge einen `Content-Type: application/json`-Header-Match für den Request hinzu.
53+
- Füge einen Request-Body mit der Adresse von Sherlock Holmes hinzu:
54+
- `recipient`: `"Sherlock Holmes"`
55+
- `city`: `"London NW1 6XE"`
56+
- `street.name`: `"Baker Street"`
57+
- `street.number`: `"221B"`
58+
- Füge einen `Content-Type: application/problem+json`-Header-Match für die Response hinzu.
59+
- Füge einen Response-Body hinzu, der ein `detail`-Feld mit einer Fehlermeldung enthält
60+
(Matcher erlaubt beliebigen Text, Beispiel: `"Addresses from UK are not supported for delivery"`).
61+
62+
Tipp: Verwende `PactDslJsonBody` (bereits als Abhängigkeit vorhanden) zum Aufbau der Bodies.
63+
64+
Wenn die Tests erfolgreich durchlaufen, werden die Pact-Dateien unter `target/pacts/` erzeugt.

customer-service/src/test/java/de/openknowledge/sample/address/domain/DeliveryAddressRepositoryTest.java

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.junit.jupiter.api.extension.ExtendWith;
3131

3232
import au.com.dius.pact.consumer.MockServer;
33-
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
3433
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
3534
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
3635
import au.com.dius.pact.consumer.junit5.PactTestFor;
@@ -49,17 +48,10 @@ public V4Pact getMax(PactDslWithProvider builder) throws IOException {
4948
return builder
5049
.given("Three customers")
5150
.uponReceiving("GET request for 0815")
52-
.path("/delivery-addresses/0815")
5351
.method("GET")
52+
.path("/delivery-addresses/0815")
5453
.willRespondWith()
5554
.status(200)
56-
.body(new PactDslJsonBody()
57-
.stringValue("recipient", "Max Mustermann")
58-
.stringValue("city", "26122 Oldenburg")
59-
.object("street")
60-
.stringValue("name", "Poststr.")
61-
.stringValue("number", "1")
62-
.closeObject())
6355
.toPact(V4Pact.class);
6456
}
6557

@@ -71,7 +63,7 @@ public V4Pact dontGetMissing(PactDslWithProvider builder) throws IOException {
7163
.path("/delivery-addresses/0817")
7264
.method("GET")
7365
.willRespondWith()
74-
.status(404)
66+
.status(204)
7567
.toPact(V4Pact.class);
7668
}
7769

@@ -83,13 +75,6 @@ public V4Pact updateMax(PactDslWithProvider builder) throws IOException {
8375
.path("/delivery-addresses/0815")
8476
.method("POST")
8577
.matchHeader("Content-Type", "application/json.*", "application/json")
86-
.body(new PactDslJsonBody()
87-
.stringValue("recipient", "Erika Mustermann")
88-
.stringValue("city", "45127 Essen")
89-
.object("street")
90-
.stringValue("name", "II. Hagen")
91-
.stringValue("number", "7")
92-
.closeObject())
9378
.willRespondWith()
9479
.status(200)
9580
.toPact(V4Pact.class);
@@ -100,20 +85,10 @@ public V4Pact dontUpdateSherlock(PactDslWithProvider builder) throws IOException
10085
return builder
10186
.given("Three customers")
10287
.uponReceiving("POST request for 007")
103-
.path("/delivery-addresses/007")
10488
.method("POST")
105-
.matchHeader("Content-Type", "application/json.*", "application/json")
106-
.body(new PactDslJsonBody()
107-
.stringValue("recipient", "Sherlock Holmes")
108-
.stringValue("city", "London NW1 6XE")
109-
.object("street")
110-
.stringValue("name", "Baker Street")
111-
.stringValue("number", "221B")
112-
.closeObject())
89+
.path("/delivery-addresses/007")
11390
.willRespondWith()
11491
.status(400)
115-
.matchHeader("Content-Type", "application/problem\\+json.*", "application/problem+json")
116-
.body(new PactDslJsonBody().stringMatcher("detail", ".*", "Addresses from UK are not supported for delivery"))
11792
.toPact(V4Pact.class);
11893
}
11994

0 commit comments

Comments
 (0)