Skip to content

Commit c9ae2ca

Browse files
committed
updated pact between Angular app and Spring provider
1 parent 5f46041 commit c9ae2ca

File tree

8 files changed

+155
-28
lines changed

8 files changed

+155
-28
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"consumer": {
3+
"name": "ui"
4+
},
5+
"provider": {
6+
"name": "userservice"
7+
},
8+
"interactions": [
9+
{
10+
"description": "a request to POST a person",
11+
"providerState": "provider accepts a new person",
12+
"request": {
13+
"method": "POST",
14+
"path": "/user-service/users",
15+
"headers": {
16+
"Content-Type": "application/json"
17+
},
18+
"body": {
19+
"firstName": "Arthur",
20+
"lastName": "Dent"
21+
}
22+
},
23+
"response": {
24+
"status": 201,
25+
"headers": {
26+
"Content-Type": "application/json"
27+
},
28+
"body": {
29+
"id": 42
30+
},
31+
"matchingRules": {
32+
"$.body": {
33+
"match": "type"
34+
}
35+
}
36+
}
37+
},
38+
{
39+
"description": "a request to PUT a person",
40+
"providerState": "person 42 exists",
41+
"request": {
42+
"method": "PUT",
43+
"path": "/user-service/users/42",
44+
"headers": {
45+
"Content-Type": "application/json"
46+
},
47+
"body": {
48+
"firstName": "Zaphod",
49+
"lastName": "Beeblebrox"
50+
},
51+
"matchingRules": {
52+
"$.body": {
53+
"match": "type"
54+
}
55+
}
56+
},
57+
"response": {
58+
"status": 200,
59+
"headers": {
60+
},
61+
"body": {
62+
"firstName": "Zaphod",
63+
"lastName": "Beeblebrox"
64+
},
65+
"matchingRules": {
66+
"$.body": {
67+
"match": "type"
68+
}
69+
}
70+
}
71+
}
72+
],
73+
"metadata": {
74+
"pactSpecification": {
75+
"version": "2.0.0"
76+
}
77+
}
78+
}

pact-angular/src/app/user.service.pact.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,41 @@ describe('UserService', () => {
9292

9393
});
9494

95+
describe('update()', () => {
96+
97+
const expectedUser: User = {
98+
firstName: 'Zaphod',
99+
lastName: 'Beeblebrox'
100+
};
101+
102+
beforeAll((done) => {
103+
provider.addInteraction({
104+
state: `person 42 exists`,
105+
uponReceiving: 'a request to PUT a person',
106+
withRequest: {
107+
method: 'PUT',
108+
path: '/user-service/users/42',
109+
body: Pact.Matchers.somethingLike(expectedUser),
110+
headers: {
111+
'Content-Type': 'application/json'
112+
}
113+
},
114+
willRespondWith: {
115+
status: 200,
116+
body: Pact.Matchers.somethingLike(expectedUser)
117+
}
118+
}).then(done, error => done.fail(error));
119+
});
120+
121+
it('should update a Person', (done) => {
122+
const userService: UserService = TestBed.get(UserService);
123+
userService.update(expectedUser, 42).subscribe(response => {
124+
done();
125+
}, error => {
126+
done.fail(error);
127+
});
128+
});
129+
130+
});
131+
95132
});

pact-spring-provider/README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
# Consumer-Driven-Contract Test for a Spring Data Rest Provider
1+
# Consumer-Driven-Contract Test for a Spring Boot Provider
22

33
This repo contains an example of consumer-driven-contract testing for a Spring
4-
Data REST API provider. The corresponding consumer to the contract is
5-
implemented in the module `pact-feign-consumer`.
4+
Boot API provider. The corresponding consumer to the contract is
5+
implemented in the module `pact-angular`.
66

77
The contract is created and verified with [Pact](https://docs.pact.io/).
88

9-
## Companion Blog Post
10-
11-
The Companion Blog Post to this project can be found [here](https://reflectoring.io/consumer-driven-contracts-with-pact-feign-spring-data-rest/).
9+
Before running the build, you need to follow the instructions on the [consumer-side](../pact-angular/)
10+
to create the consumer-driven contract file (pact file).
1211

1312
## Running the application
1413

15-
The interesting part in this code base is the class `ProviderPactVerificationTest`.
14+
The interesting part in this code base is the class `UserControllerProviderTest`.
1615
You can run the tests with `gradlew test` on Windows or `./gradlew test` on Unix.

pact-spring-provider/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ dependencies {
2626
compile('org.springframework.boot:spring-boot-starter-data-jpa')
2727
compile('org.springframework.boot:spring-boot-starter-web')
2828
compile('com.h2database:h2:1.4.196')
29-
testCompile('au.com.dius:pact-jvm-provider-spring_2.12:3.5.8')
29+
testCompile('au.com.dius:pact-jvm-provider-spring_2.12:3.5.9')
3030
testCompile('junit:junit:4.12')
3131
testCompile('org.springframework.boot:spring-boot-starter-test')
3232
}

pact-spring-provider/gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
33
zipStoreBase=GRADLE_USER_HOME
44
zipStorePath=wrapper/dists
5-
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-bin.zip
5+
distributionUrl=https\://services.gradle.org/distributions/gradle-4.2-bin.zip

pact-spring-provider/src/main/java/com/example/demo/User.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,9 @@ public String getLastName() {
4444
public void setLastName(String lastName) {
4545
this.lastName = lastName;
4646
}
47+
48+
public void updateFrom(User user){
49+
this.firstName = user.getFirstName();
50+
this.lastName = user.getLastName();
51+
}
4752
}

pact-spring-provider/src/main/java/com/example/demo/UserController.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.example.demo;
22

33
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.http.MediaType;
45
import org.springframework.http.ResponseEntity;
56
import org.springframework.web.bind.annotation.*;
67

@@ -24,6 +25,14 @@ public ResponseEntity<IdObject> createUser(@RequestBody @Valid User user) {
2425
.body(new IdObject(savedUser.getId()));
2526
}
2627

28+
@PutMapping(path = "/user-service/users/{id}")
29+
public ResponseEntity<User> updateUser(@RequestBody @Valid User user, @PathVariable long id) {
30+
User userFromDb = userRepository.findOne(id);
31+
userFromDb.updateFrom(user);
32+
userFromDb = userRepository.save(userFromDb);
33+
return ResponseEntity.ok(userFromDb);
34+
}
35+
2736
@GetMapping(path = "/user-service/users/{id}")
2837
public ResponseEntity<User> getUser(@PathVariable("id") Long id) {
2938
return ResponseEntity.ok(userRepository.findOne(id));

pact-spring-provider/src/test/java/com/example/demo/UserControllerProviderTest.java

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,41 @@
22

33
import au.com.dius.pact.provider.junit.Provider;
44
import au.com.dius.pact.provider.junit.State;
5-
import au.com.dius.pact.provider.junit.loader.PactBroker;
6-
import au.com.dius.pact.provider.junit.loader.PactBrokerAuth;
5+
import au.com.dius.pact.provider.junit.loader.PactFolder;
76
import au.com.dius.pact.provider.junit.target.HttpTarget;
87
import au.com.dius.pact.provider.junit.target.Target;
98
import au.com.dius.pact.provider.junit.target.TestTarget;
109
import au.com.dius.pact.provider.spring.SpringRestPactRunner;
1110
import org.junit.runner.RunWith;
1211
import org.springframework.boot.test.context.SpringBootTest;
1312
import org.springframework.boot.test.mock.mockito.MockBean;
14-
13+
import static org.mockito.Matchers.eq;
1514
import static org.mockito.Mockito.any;
1615
import static org.mockito.Mockito.when;
1716

1817
@RunWith(SpringRestPactRunner.class)
1918
@Provider("userservice")
20-
@PactBroker(host = "adesso.pact.dius.com.au/", port = "80", protocol = "https", authentication =
21-
@PactBrokerAuth(username = "Vm6YWrQURJ1T7mDIRiKwfexCAc4HbU", password = "aLerJwBhpEcN0Wm88Wgvs45AR9dXpc")
22-
)
19+
@PactFolder("../pact-angular/pacts")
2320
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = {
24-
"server.port=8080"
21+
"server.port=8080"
2522
})
2623
public class UserControllerProviderTest {
2724

28-
@MockBean
29-
private UserRepository userRepository;
25+
@MockBean
26+
private UserRepository userRepository;
3027

31-
@TestTarget
32-
public final Target target = new HttpTarget(8080);
28+
@TestTarget
29+
public final Target target = new HttpTarget(8080);
3330

34-
@State("provider accepts a new person")
35-
public void toCreatePersonState() {
36-
User user = new User();
37-
user.setId(42L);
38-
user.setFirstName("Arthur");
39-
user.setLastName("Dent");
40-
when(userRepository.save(any(User.class))).thenReturn(user);
41-
}
31+
@State({"provider accepts a new person",
32+
"person 42 exists"})
33+
public void toCreatePersonState() {
34+
User user = new User();
35+
user.setId(42L);
36+
user.setFirstName("Arthur");
37+
user.setLastName("Dent");
38+
when(userRepository.findOne(eq(42L))).thenReturn(user);
39+
when(userRepository.save(any(User.class))).thenReturn(user);
40+
}
4241

4342
}

0 commit comments

Comments
 (0)