Compare commits
7 Commits
pact-feign
...
pact-jvm-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8216c90168 | ||
|
|
fe9e15b813 | ||
|
|
9e66b87b18 | ||
|
|
9bae6d560a | ||
|
|
9d58b1323e | ||
|
|
612863cb2a | ||
|
|
f854262f80 |
0
.idea/modules/spring-boot-testing.iml
generated
Normal file
0
.idea/modules/spring-boot-testing.iml
generated
Normal file
@@ -1,13 +1,11 @@
|
||||
# Testing a Spring Boot REST API Consumer against a Contract with Spring Cloud Contract
|
||||
# Testing a Spring Boot REST API Consumer against a Contract with Pact
|
||||
|
||||
## Companion Blog Article
|
||||
Read the [companion blog article](https://reflectoring.io/consumer-driven-contract-consumer-spring-cloud-contract/) to this repository.
|
||||
Read the [companion blog article](http://localhost:4000/consumer-driven-contract-feign-pact/) to this repository.
|
||||
|
||||
## Getting Started
|
||||
|
||||
* have a look at the [contract](/src/test/resources/contracts)
|
||||
* have a look at the [feign client](/src/main/java/io/reflectoring/UserClient.java)
|
||||
* have a look at the [consumer test](/src/test/java/io/reflectoring/UserClientTest.java)
|
||||
* run `./gradlew publishToMavenLocal` in the [producer project](../spring-cloud-contract-provider)
|
||||
to create a provider stubs
|
||||
* run `./gradlew build` in this project to verify the feign client against the stub
|
||||
* have a look at the [feign client](src/main/java/io/reflectoring/UserClient.java)
|
||||
* have a look at the [consumer test](src/test/java/io/reflectoring/UserServiceConsumerTest.java)
|
||||
* run `./gradlew build` in this project to create a pact and run the consumer test
|
||||
* afterwards, find the pact contract file in the folder `target/pacts`
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
userservice:
|
||||
ribbon:
|
||||
eureka:
|
||||
enabled: false
|
||||
listOfServers: localhost:8080
|
||||
|
||||
rootservice:
|
||||
ribbon:
|
||||
eureka:
|
||||
enabled: false
|
||||
|
||||
@@ -22,6 +22,6 @@ dependencies {
|
||||
compile("org.springframework.cloud:spring-cloud-starter-feign:1.4.1.RELEASE")
|
||||
compile('com.h2database:h2:1.4.196')
|
||||
testCompile('org.codehaus.groovy:groovy-all:2.4.6')
|
||||
testCompile("au.com.dius:pact-jvm-consumer-junit_2.11:3.5.2")
|
||||
compile("au.com.dius:pact-jvm-consumer-junit_2.11:3.5.16")
|
||||
testCompile("org.springframework.boot:spring-boot-starter-test:${springboot_version}")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
package io.reflectoring.dsl;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
|
||||
import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue;
|
||||
|
||||
public class PactDslJsonBodyLikeMapper {
|
||||
|
||||
private static final Set<Class<?>> SIMPLE_TYPES = new HashSet<>(Arrays.asList(
|
||||
Boolean.class,
|
||||
boolean.class,
|
||||
Integer.class,
|
||||
int.class,
|
||||
Double.class,
|
||||
double.class,
|
||||
Float.class,
|
||||
float.class,
|
||||
BigDecimal.class,
|
||||
Number.class,
|
||||
String.class,
|
||||
Long.class,
|
||||
long.class
|
||||
));
|
||||
|
||||
public static PactDslJsonBody like(Object object) {
|
||||
return like(object, new PactDslJsonBody());
|
||||
}
|
||||
|
||||
public static PactDslJsonBody like(Object object, PactDslJsonBody body) {
|
||||
try {
|
||||
return recursiveLike(object, body);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("could not create PactDslJsonBody due to exception!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static PactDslJsonBody recursiveLike(Object object, PactDslJsonBody body) throws IllegalAccessException {
|
||||
Field[] fields = object.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
|
||||
Object fieldValue = field.get(object);
|
||||
|
||||
if (fieldValue == null) {
|
||||
// fields with null values will not be mapped
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isSimpleType(field.getType())) {
|
||||
mapSimpleFieldWithName(field.getName(), fieldValue, body);
|
||||
} else if (isCollectionType(field.getType())) {
|
||||
mapCollectionField(field.getName(), (Collection) fieldValue, body);
|
||||
} else {
|
||||
mapComplexField(field.getName(), fieldValue, body);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
private static void mapSimpleFieldWithName(String fieldName, Object fieldValue, PactDslJsonBody body) throws IllegalAccessException {
|
||||
Class<?> type = fieldValue.getClass();
|
||||
if (String.class == type) {
|
||||
body.stringType(fieldName, (String) fieldValue);
|
||||
} else if (Boolean.class == type || boolean.class == type) {
|
||||
body.booleanType(fieldName, (Boolean) fieldValue);
|
||||
} else if (Integer.class == type || int.class == type || Long.class == type || long.class == type) {
|
||||
body.integerType(fieldName, (Integer) fieldValue);
|
||||
} else if (Double.class == type || double.class == type) {
|
||||
body.decimalType(fieldName, (Double) fieldValue);
|
||||
} else if (Float.class == type || float.class == type) {
|
||||
body.decimalType(fieldName, ((Float) fieldValue).doubleValue());
|
||||
} else if (BigDecimal.class == type) {
|
||||
body.decimalType(fieldName, (BigDecimal) fieldValue);
|
||||
} else if (Number.class.isAssignableFrom(type)) {
|
||||
body.numberType(fieldName, (Number) fieldValue);
|
||||
} else {
|
||||
throw new IllegalStateException(String.format("field '%s' of type '%s' is not a simple field", fieldName, type));
|
||||
}
|
||||
}
|
||||
|
||||
private static PactDslJsonRootValue getRootValueForType(Class<?> type) {
|
||||
if (String.class == type) {
|
||||
return PactDslJsonRootValue.stringType();
|
||||
} else if (Boolean.class == type || boolean.class == type) {
|
||||
return PactDslJsonRootValue.booleanType();
|
||||
} else if (Integer.class == type || int.class == type || Long.class == type || long.class == type) {
|
||||
return PactDslJsonRootValue.integerType();
|
||||
} else if (Double.class == type || double.class == type) {
|
||||
return PactDslJsonRootValue.decimalType();
|
||||
} else if (Float.class == type || float.class == type) {
|
||||
return PactDslJsonRootValue.decimalType();
|
||||
} else if (BigDecimal.class == type) {
|
||||
return PactDslJsonRootValue.decimalType();
|
||||
} else if (Number.class.isAssignableFrom(type)) {
|
||||
return PactDslJsonRootValue.numberType();
|
||||
} else {
|
||||
throw new IllegalStateException(String.format("unsupported type '%s'", type));
|
||||
}
|
||||
}
|
||||
|
||||
private static void mapCollectionField(String fieldName, Collection<?> collection, PactDslJsonBody body) throws IllegalAccessException {
|
||||
if (collection.isEmpty()) {
|
||||
throw new IllegalArgumentException("matching empty lists is not supported!");
|
||||
}
|
||||
|
||||
Class<?> listType = collection.iterator().next().getClass();
|
||||
|
||||
if (isSimpleType(listType)) {
|
||||
PactDslJsonRootValue rootValue = getRootValueForType(listType);
|
||||
body.eachLike(fieldName, rootValue);
|
||||
} else if (isCollectionType(listType)) {
|
||||
throw new IllegalArgumentException("collections of collections are not supported");
|
||||
} else {
|
||||
PactDslJsonBody nestedBody = body.eachLike(fieldName);
|
||||
for (Object complexObject : collection) {
|
||||
mapComplexFieldWithoutOpeningObject(complexObject, nestedBody);
|
||||
}
|
||||
nestedBody.closeObject().closeArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void mapComplexField(String fieldName, Object fieldValue, PactDslJsonBody body) throws IllegalAccessException {
|
||||
PactDslJsonBody nestedBody = body.object(fieldName);
|
||||
mapComplexFieldWithoutOpeningObject(fieldValue, nestedBody);
|
||||
}
|
||||
|
||||
private static void mapComplexFieldWithoutOpeningObject(Object fieldValue, PactDslJsonBody nestedBody) throws IllegalAccessException {
|
||||
recursiveLike(fieldValue, nestedBody);
|
||||
nestedBody.closeObject();
|
||||
}
|
||||
|
||||
private static boolean isSimpleType(Class<?> type) {
|
||||
return SIMPLE_TYPES.contains(type);
|
||||
}
|
||||
|
||||
private static boolean isCollectionType(Class<?> type) {
|
||||
return Collection.class.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package io.reflectoring.dsl;
|
||||
|
||||
public class Nested {
|
||||
|
||||
private String stringField = "nested string";
|
||||
private Integer integerField = 42;
|
||||
private String nullField = null;
|
||||
|
||||
public String getStringField() {
|
||||
return stringField;
|
||||
}
|
||||
|
||||
public void setStringField(String stringField) {
|
||||
this.stringField = stringField;
|
||||
}
|
||||
|
||||
public Integer getIntegerField() {
|
||||
return integerField;
|
||||
}
|
||||
|
||||
public void setIntegerField(Integer integerField) {
|
||||
this.integerField = integerField;
|
||||
}
|
||||
|
||||
public String getNullField() {
|
||||
return nullField;
|
||||
}
|
||||
|
||||
public void setNullField(String nullField) {
|
||||
this.nullField = nullField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package io.reflectoring.dsl;
|
||||
|
||||
import au.com.dius.pact.consumer.Pact;
|
||||
import au.com.dius.pact.consumer.PactProviderRuleMk2;
|
||||
import au.com.dius.pact.consumer.PactVerification;
|
||||
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
|
||||
import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue;
|
||||
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
|
||||
import au.com.dius.pact.model.RequestResponsePact;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(properties = {
|
||||
// overriding provider address
|
||||
"rootservice.ribbon.listOfServers: localhost:8888"
|
||||
})
|
||||
public class PactDslJsonBodyLikeMapperConsumerTest {
|
||||
|
||||
@Rule
|
||||
public PactProviderRuleMk2 stubProvider = new PactProviderRuleMk2("testprovider", "localhost", 8888, this);
|
||||
|
||||
@Autowired
|
||||
private RootClient rootClient;
|
||||
|
||||
@Pact(state = "teststate", provider = "testprovider", consumer = "testclient")
|
||||
public RequestResponsePact createPact(PactDslWithProvider builder) {
|
||||
return builder
|
||||
.given("teststate")
|
||||
.uponReceiving("a POST request with a Root object")
|
||||
.path("/root")
|
||||
.method("POST")
|
||||
// .body(PactDslJsonBodyLikeMapper.like(new PactDslJsonBodyLikeMapperTest.Root()))
|
||||
.willRespondWith()
|
||||
.status(201)
|
||||
.matchHeader("Content-Type", "application/json")
|
||||
.body(PactDslJsonBodyLikeMapper.like(new Root()))
|
||||
.toPact();
|
||||
}
|
||||
|
||||
@Pact(state = "teststate2", provider = "testprovider", consumer = "testclient")
|
||||
public RequestResponsePact createPact2(PactDslWithProvider builder) {
|
||||
return builder
|
||||
.given("teststate2")
|
||||
.uponReceiving("a POST request with a Root object")
|
||||
.path("/root")
|
||||
.method("POST")
|
||||
.willRespondWith()
|
||||
.status(201)
|
||||
.matchHeader("Content-Type", "application/json")
|
||||
.body(new PactDslJsonBody()
|
||||
.eachLike("arrayField", PactDslJsonRootValue.numberType()))
|
||||
.toPact();
|
||||
}
|
||||
|
||||
@Test
|
||||
@PactVerification(fragment = "createPact")
|
||||
public void verifyPact() {
|
||||
rootClient.createRoot(new Root());
|
||||
}
|
||||
|
||||
@Test
|
||||
@PactVerification(fragment = "createPact2")
|
||||
public void verifyPact2() {
|
||||
rootClient.createRoot(new Root());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package io.reflectoring.dsl;
|
||||
|
||||
|
||||
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class PactDslJsonBodyLikeMapperTest {
|
||||
|
||||
@Test
|
||||
public void createsMatchersForAllFields() {
|
||||
Root object = new Root();
|
||||
PactDslJsonBody jsonBody = PactDslJsonBodyLikeMapper.like(object);
|
||||
assertNoMatcher(jsonBody, ".nullField");
|
||||
assertMatcherType(jsonBody, ".stringField", "type");
|
||||
assertMatcherType(jsonBody, ".booleanField", "type");
|
||||
assertMatcherType(jsonBody, ".primitiveBooleanField", "type");
|
||||
assertMatcherType(jsonBody, ".integerField", "integer");
|
||||
assertMatcherType(jsonBody, ".primitiveIntegerField", "integer");
|
||||
assertMatcherType(jsonBody, ".doubleField", "decimal");
|
||||
assertMatcherType(jsonBody, ".primitiveDoubleField", "decimal");
|
||||
assertMatcherType(jsonBody, ".floatField", "decimal");
|
||||
assertMatcherType(jsonBody, ".primitiveFloatField", "decimal");
|
||||
assertMatcherType(jsonBody, ".bigDecimalField", "decimal");
|
||||
assertMatcherType(jsonBody, ".numberField", "number");
|
||||
assertMatcherType(jsonBody, ".nested.stringField", "type");
|
||||
assertMatcherType(jsonBody, ".nested.integerField", "integer");
|
||||
assertNoMatcher(jsonBody, ".nested.nullField");
|
||||
assertMatcherType(jsonBody, ".complexListField[*].stringField", "type");
|
||||
assertMatcherType(jsonBody, ".complexListField[*].integerField", "integer");
|
||||
assertMatcherType(jsonBody, ".simpleListField[*]", "integer");
|
||||
}
|
||||
|
||||
private void assertMatcherType(PactDslJsonBody jsonBody, String fieldName, String expectedMatcher) {
|
||||
assertMatcher(jsonBody, fieldName);
|
||||
assertEquals(String.format("expected matcher for field '%s' to be of type '%s'", fieldName, expectedMatcher),
|
||||
ImmutableMap.of("match", expectedMatcher),
|
||||
jsonBody.getMatchers().getMatchingRules().get(fieldName).getRules().get(0).toMap());
|
||||
}
|
||||
|
||||
private void assertMatcher(PactDslJsonBody jsonBody, String fieldName) {
|
||||
assertNotNull(String.format("expected a matcher for field '%s'", fieldName),
|
||||
jsonBody.getMatchers().getMatchingRules().get(fieldName));
|
||||
}
|
||||
|
||||
private void assertNoMatcher(PactDslJsonBody jsonBody, String fieldName) {
|
||||
assertNull(jsonBody.getMatchers().getMatchingRules().get(fieldName));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package io.reflectoring.dsl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Root {
|
||||
|
||||
private String nullField = null;
|
||||
private String stringField = "string";
|
||||
private Boolean booleanField = Boolean.TRUE;
|
||||
private Integer integerField = 1;
|
||||
private Double doubleField = 1d;
|
||||
private Float floatField = 1f;
|
||||
private BigDecimal bigDecimalField = BigDecimal.ONE;
|
||||
private boolean primitiveBooleanField = true;
|
||||
private int primitiveIntegerField = 1;
|
||||
private double primitiveDoubleField = 1d;
|
||||
private float primitiveFloatField = 1f;
|
||||
private Number numberField = BigInteger.valueOf(1L);
|
||||
private Nested nested = new Nested();
|
||||
private List<Nested> complexListField = Arrays.asList(new Nested(), new Nested());
|
||||
private List<Integer> simpleListField = Arrays.asList(1,2);
|
||||
|
||||
public String getNullField() {
|
||||
return nullField;
|
||||
}
|
||||
|
||||
public void setNullField(String nullField) {
|
||||
this.nullField = nullField;
|
||||
}
|
||||
|
||||
public String getStringField() {
|
||||
return stringField;
|
||||
}
|
||||
|
||||
public void setStringField(String stringField) {
|
||||
this.stringField = stringField;
|
||||
}
|
||||
|
||||
public Boolean getBooleanField() {
|
||||
return booleanField;
|
||||
}
|
||||
|
||||
public void setBooleanField(Boolean booleanField) {
|
||||
this.booleanField = booleanField;
|
||||
}
|
||||
|
||||
public Integer getIntegerField() {
|
||||
return integerField;
|
||||
}
|
||||
|
||||
public void setIntegerField(Integer integerField) {
|
||||
this.integerField = integerField;
|
||||
}
|
||||
|
||||
public Double getDoubleField() {
|
||||
return doubleField;
|
||||
}
|
||||
|
||||
public void setDoubleField(Double doubleField) {
|
||||
this.doubleField = doubleField;
|
||||
}
|
||||
|
||||
public Float getFloatField() {
|
||||
return floatField;
|
||||
}
|
||||
|
||||
public void setFloatField(Float floatField) {
|
||||
this.floatField = floatField;
|
||||
}
|
||||
|
||||
public BigDecimal getBigDecimalField() {
|
||||
return bigDecimalField;
|
||||
}
|
||||
|
||||
public void setBigDecimalField(BigDecimal bigDecimalField) {
|
||||
this.bigDecimalField = bigDecimalField;
|
||||
}
|
||||
|
||||
public boolean isPrimitiveBooleanField() {
|
||||
return primitiveBooleanField;
|
||||
}
|
||||
|
||||
public void setPrimitiveBooleanField(boolean primitiveBooleanField) {
|
||||
this.primitiveBooleanField = primitiveBooleanField;
|
||||
}
|
||||
|
||||
public int getPrimitiveIntegerField() {
|
||||
return primitiveIntegerField;
|
||||
}
|
||||
|
||||
public void setPrimitiveIntegerField(int primitiveIntegerField) {
|
||||
this.primitiveIntegerField = primitiveIntegerField;
|
||||
}
|
||||
|
||||
public double getPrimitiveDoubleField() {
|
||||
return primitiveDoubleField;
|
||||
}
|
||||
|
||||
public void setPrimitiveDoubleField(double primitiveDoubleField) {
|
||||
this.primitiveDoubleField = primitiveDoubleField;
|
||||
}
|
||||
|
||||
public float getPrimitiveFloatField() {
|
||||
return primitiveFloatField;
|
||||
}
|
||||
|
||||
public void setPrimitiveFloatField(float primitiveFloatField) {
|
||||
this.primitiveFloatField = primitiveFloatField;
|
||||
}
|
||||
|
||||
public Number getNumberField() {
|
||||
return numberField;
|
||||
}
|
||||
|
||||
public void setNumberField(Number numberField) {
|
||||
this.numberField = numberField;
|
||||
}
|
||||
|
||||
public Nested getNested() {
|
||||
return nested;
|
||||
}
|
||||
|
||||
public void setNested(Nested nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
public List<Nested> getComplexListField() {
|
||||
return complexListField;
|
||||
}
|
||||
|
||||
public void setComplexListField(List<Nested> complexListField) {
|
||||
this.complexListField = complexListField;
|
||||
}
|
||||
|
||||
public List<Integer> getSimpleListField() {
|
||||
return simpleListField;
|
||||
}
|
||||
|
||||
public void setSimpleListField(List<Integer> simpleListField) {
|
||||
this.simpleListField = simpleListField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.reflectoring.dsl;
|
||||
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
@FeignClient(name = "rootservice")
|
||||
public interface RootClient {
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST, path = "/root")
|
||||
Root createRoot(@RequestBody Root root);
|
||||
|
||||
}
|
||||
11
pact/pact-spring-provider/application.yml
Normal file
11
pact/pact-spring-provider/application.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||
driverClassName: org.h2.Driver
|
||||
username: sa
|
||||
password:
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
|
||||
logging.level.org.hibernate.SQL: OFF
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.demo;
|
||||
package io.reflectoring;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.demo;
|
||||
package io.reflectoring;
|
||||
|
||||
public class IdObject {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.demo;
|
||||
package io.reflectoring;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.example.demo;
|
||||
package io.reflectoring;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.demo;
|
||||
package io.reflectoring;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
spring.datasource.url=jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.h2.console.enabled=true
|
||||
|
||||
logging.level.org.hibernate.SQL=OFF
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.demo;
|
||||
package io.reflectoring;
|
||||
|
||||
import au.com.dius.pact.provider.junit.Provider;
|
||||
import au.com.dius.pact.provider.junit.State;
|
||||
@@ -7,6 +7,8 @@ import au.com.dius.pact.provider.junit.target.HttpTarget;
|
||||
import au.com.dius.pact.provider.junit.target.Target;
|
||||
import au.com.dius.pact.provider.junit.target.TestTarget;
|
||||
import au.com.dius.pact.provider.spring.SpringRestPactRunner;
|
||||
import io.reflectoring.User;
|
||||
import io.reflectoring.UserRepository;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
@@ -5,7 +5,7 @@ Read the [companion blog article](https://reflectoring.io/consumer-driven-contra
|
||||
|
||||
## Getting Started
|
||||
|
||||
* have a look at the [contract](/src/test/resources/contracts)
|
||||
* have a look at the [controller](/src/main/java/io/reflectoring/UserController.java)
|
||||
* have a look at the [contract](src/test/resources/contracts/userservice)
|
||||
* have a look at the [controller](src/main/java/io/reflectoring/UserController.java)
|
||||
* run `./gradlew generateContractTests` to generate JUnit tests that validate the controller against the contract
|
||||
* run `./gradlew build` to generate and run the tests
|
||||
* run `./gradlew build` to generate and run the tests
|
||||
|
||||
Reference in New Issue
Block a user