Fixed missing regex value generation

without this change the autogenerated tests were wrong and contained a 'cursor' value
with this change it got fixed

fixes #168
This commit is contained in:
Marcin Grzejszczak
2016-12-14 21:58:01 +01:00
parent e3056a4978
commit f9961d17f6
6 changed files with 81 additions and 52 deletions

View File

@@ -590,7 +590,7 @@ org.springframework.cloud.contract.spec.Contract.make {
loanAmount: 99999
])
headers { // (5)
header('Content-Type', 'application/vnd.fraud.v1+json')
contentType("application/vnd.fraud.v1+json")
}
}
response { // (6)
@@ -600,10 +600,7 @@ org.springframework.cloud.contract.spec.Contract.make {
rejectionReason: "Amount too high"
])
headers { // (9)
header('Content-Type': value(
producer(regex('application/vnd.fraud.v1.json.*')),
consumer('application/vnd.fraud.v1+json'))
)
contentType("application/vnd.fraud.v1+json")
}
}
}
@@ -871,16 +868,28 @@ That's because all the generated tests will extend that class. Over there you ca
----
package com.example.fraud;
import com.example.fraud.FraudDetectionController;
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc;
public class FraudBase {
@Before
public void setup() {
RestAssuredMockMvc.standaloneSetup(new FraudDetectionController());
RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(),
new FraudStatsController(stubbedStatsProvider()));
}
private StatsProvider stubbedStatsProvider() {
return fraudType -> {
switch (fraudType) {
case DRUNKS:
return 100;
case ALL:
return 200;
}
return 0;
};
}
public void assertThatRejectionReasonIsNull(Object rejectionReason) {
@@ -1312,7 +1321,7 @@ Example of a `pom.xml` inside the `server` folder.
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring-cloud-contract.version>1.1.0.BUILD-SNAPSHOT</spring-cloud-contract.version>
<spring-cloud-dependencies.version>Camden.BUILD-SNAPSHOT</spring-cloud-dependencies.version>
<spring-cloud-dependencies.version>Dalston.BUILD-SNAPSHOT</spring-cloud-dependencies.version>
</properties>
<dependencyManagement>

View File

@@ -3,13 +3,13 @@ package contracts
org.springframework.cloud.contract.spec.Contract.make {
request { // (1)
method 'PUT' // (2)
url '/fraudcheck1' // (3)
url '/fraudcheck' // (3)
body([ // (4)
clientId: value(consumer(regex('[0-9]{10}'))),
clientId: $(regex('[0-9]{10}')),
loanAmount: 99999
])
headers { // (5)
header('Content-Type', 'application/vnd.fraud.v1+json')
contentType('application/vnd.fraud.v1+json')
}
}
response { // (6)
@@ -19,21 +19,20 @@ org.springframework.cloud.contract.spec.Contract.make {
rejectionReason: "Amount too high"
])
headers { // (9)
header('Content-Type': value(
producer(regex('application/vnd.fraud.v1.json.*')),
consumer('application/vnd.fraud.v1+json'))
)
contentType('application/vnd.fraud.v1+json')
}
}
}
/*
Since we don't want to force on the user to hardcode values of fields that are dynamic
(timestamps, database ids etc.), one can provide parametrize those entries by using the
`value(consumer(...), producer(...))` method. That way what's present in the `consumer`
section will end up in the produced stub. What's there in the `producer` will end up in the
autogenerated test. If you provide only the regular expression side without the concrete
value then Spring Cloud Contract will generate one for you.
(timestamps, database ids etc.), one can parametrize those entries. If you wrap your field's
value in a `$(...)` or `value(...)` and provide a dynamic value of a field then
the concrete value will be generated for you. If you want to be really explicit about
which side gets which value you can do that by using the `value(consumer(...), producer(...))` notation.
That way what's present in the `consumer` section will end up in the produced stub. What's
there in the `producer` will end up in the autogenerated test. If you provide only the
regular expression side without the concrete value then Spring Cloud Contract will generate one for you.
From the Consumer perspective, when shooting a request in the integration test:

View File

@@ -1,39 +1,38 @@
package contracts
org.springframework.cloud.contract.spec.Contract.make {
request { // (1)
method 'PUT' // (2)
url '/fraudcheck' // (3)
body([ // (4)
clientId: value(consumer(regex('[0-9]{10}'))),
loanAmount: 99999
])
headers { // (5)
header('Content-Type', 'application/vnd.fraud.v1+json')
}
}
response { // (6)
status 200 // (7)
body([ // (8)
fraudCheckStatus: "FRAUD",
rejectionReason: "Amount too high"
])
headers { // (9)
header('Content-Type': value(
producer(regex('application/vnd.fraud.v1.json.*')),
consumer('application/vnd.fraud.v1+json'))
)
}
}
request { // (1)
method 'PUT' // (2)
url '/fraudcheck' // (3)
body([ // (4)
clientId: $(regex('[0-9]{10}')),
loanAmount: 99999
])
headers { // (5)
contentType('application/vnd.fraud.v1+json')
}
}
response { // (6)
status 200 // (7)
body([ // (8)
fraudCheckStatus: "FRAUD",
rejectionReason: "Amount too high"
])
headers { // (9)
contentType('application/vnd.fraud.v1+json')
}
}
}
/*
Since we don't want to force on the user to hardcode values of fields that are dynamic
(timestamps, database ids etc.), one can provide parametrize those entries by using the
`value(consumer(...), producer(...))` method. That way what's present in the `consumer`
section will end up in the produced stub. What's there in the `producer` will end up in the
autogenerated test. If you provide only the regular expression side without the concrete
value then Spring Cloud Contract will generate one for you.
(timestamps, database ids etc.), one can parametrize those entries. If you wrap your field's
value in a `$(...)` or `value(...)` and provide a dynamic value of a field then
the concrete value will be generated for you. If you want to be really explicit about
which side gets which value you can do that by using the `value(consumer(...), producer(...))` notation.
That way what's present in the `consumer` section will end up in the produced stub. What's
there in the `producer` will end up in the autogenerated test. If you provide only the
regular expression side without the concrete value then Spring Cloud Contract will generate one for you.
From the Consumer perspective, when shooting a request in the integration test:

View File

@@ -196,6 +196,14 @@ class Request extends Common {
return value(client)
}
DslProperty value(Pattern client) {
return value(new ClientDslProperty(client))
}
DslProperty $(Pattern client) {
return value(client)
}
@Override
DslProperty value(ClientDslProperty client, ServerDslProperty server) {
if (server.clientValue instanceof Pattern) {

View File

@@ -103,6 +103,14 @@ class Response extends Common {
return value(server)
}
DslProperty value(Pattern server) {
return value(new ServerDslProperty(server))
}
DslProperty $(Pattern server) {
return value(server)
}
@Override
DslProperty value(ClientDslProperty client, ServerDslProperty server) {
if (client.clientValue instanceof Pattern) {

View File

@@ -1697,6 +1697,7 @@ World.'''"""
}
@Issue('#149')
@Unroll
def "should allow easier way of providing dynamic values"() {
given:
Contract contractDsl = Contract.make {
@@ -1704,6 +1705,7 @@ World.'''"""
method 'GET'
urlPath '/get'
body([
duck: $(regex("[0-9]")),
alpha: $(anyAlphaUnicode()),
number: $(anyNumber()),
aBoolean: $(aBoolean()),
@@ -1734,7 +1736,7 @@ World.'''"""
}
}
}
MethodBodyBuilder builder = new MockMvcSpockMethodRequestProcessingBodyBuilder(contractDsl, properties)
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
@@ -1749,6 +1751,10 @@ World.'''"""
test.contains('assertThatJson(parsedJson).field("ip").matches("([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])")')
test.contains('assertThatJson(parsedJson).field("uuid").matches("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}")')
!test.contains('cursor')
where:
methodBuilder << [{ Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties)},
{ Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties)}]
}
@Issue('#162')