Merge remote-tracking branch 'origin/master'

# Conflicts:
#	spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy
#	spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/ContentUtilsSpec.groovy
This commit is contained in:
Olga Maciaszek-Sharma
2019-02-13 13:27:55 +01:00
1272 changed files with 31933 additions and 20845 deletions

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier
@@ -48,9 +48,9 @@ class GeneratorScannerSpec extends Specification {
when:
testGenerator.generateTestClasses("org.springframework.cloud.contract.verifier")
then:
1 * classGenerator.buildClass(_, _, _, { SingleTestGenerator.GeneratedClassData it -> it.className == 'exceptionsSpec' && it.classPackage == 'org.springframework.cloud.contract.verifier'} ) >> "spec"
1 * classGenerator.buildClass(_, _, _, { SingleTestGenerator.GeneratedClassData it -> it.className == 'exceptionsSpec' && it.classPackage == 'org.springframework.cloud.contract.verifier.v1'} ) >> "spec1"
1 * classGenerator.buildClass(_, _, _, { SingleTestGenerator.GeneratedClassData it -> it.className == 'exceptionsSpec' && it.classPackage == 'org.springframework.cloud.contract.verifier.v2'} ) >> "spec2"
1 * classGenerator.buildClass(_, _, _, { SingleTestGenerator.GeneratedClassData it -> it.className == 'exceptionsSpec' && it.classPackage == 'org.springframework.cloud.contract.verifier' }) >> "spec"
1 * classGenerator.buildClass(_, _, _, { SingleTestGenerator.GeneratedClassData it -> it.className == 'exceptionsSpec' && it.classPackage == 'org.springframework.cloud.contract.verifier.v1' }) >> "spec1"
1 * classGenerator.buildClass(_, _, _, { SingleTestGenerator.GeneratedClassData it -> it.className == 'exceptionsSpec' && it.classPackage == 'org.springframework.cloud.contract.verifier.v2' }) >> "spec2"
}
def "should create class with name with hyphen"() {
@@ -61,7 +61,7 @@ class GeneratorScannerSpec extends Specification {
when:
testGenerator.generateTestClasses("org.springframework.cloud.contract.verifier")
then:
1 * classGenerator.buildClass(_, _, _, { SingleTestGenerator.GeneratedClassData it -> it.className == 'car_rentalSpec' && it.classPackage == 'org.springframework.cloud.contract.verifier'} ) >> "spec"
1 * classGenerator.buildClass(_, _, _, { SingleTestGenerator.GeneratedClassData it -> it.className == 'car_rentalSpec' && it.classPackage == 'org.springframework.cloud.contract.verifier' }) >> "spec"
}
}

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.assertion;
import java.util.ArrayList;
@@ -26,10 +42,13 @@ public class CollectionAssertTests {
Collection collection = collection();
try {
SpringCloudContractAssertions.assertThat(collection).allElementsMatch("[0-9]");
SpringCloudContractAssertions.assertThat(collection)
.allElementsMatch("[0-9]");
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("The value <a> doesn't match the regex <[0-9]>");
}
catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining(
"The value <a> doesn't match the regex <[0-9]>");
}
}
@@ -38,10 +57,13 @@ public class CollectionAssertTests {
Collection collection = collectionWithNulls();
try {
SpringCloudContractAssertions.assertThat(collection).allElementsMatch("[0-9]");
SpringCloudContractAssertions.assertThat(collection)
.allElementsMatch("[0-9]");
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("The value <null> doesn't match the regex <[0-9]>");
}
catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining(
"The value <null> doesn't match the regex <[0-9]>");
}
}
@@ -52,8 +74,10 @@ public class CollectionAssertTests {
try {
SpringCloudContractAssertions.assertThat(collection).allElementsMatch("foo");
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("Expecting actual not to be null");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("Expecting actual not to be null");
}
}
@@ -64,8 +88,10 @@ public class CollectionAssertTests {
try {
SpringCloudContractAssertions.assertThat(collection).allElementsMatch("foo");
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("Expecting actual not to be empty");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("Expecting actual not to be empty");
}
}
@@ -83,10 +109,13 @@ public class CollectionAssertTests {
Collection collection = nestedCollection();
try {
SpringCloudContractAssertions.assertThat(collection).hasFlattenedSizeGreaterThanOrEqualTo(5);
SpringCloudContractAssertions.assertThat(collection)
.hasFlattenedSizeGreaterThanOrEqualTo(5);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("The flattened size <4> is not greater or equal to <5>");
}
catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining(
"The flattened size <4> is not greater or equal to <5>");
}
}
@@ -95,10 +124,13 @@ public class CollectionAssertTests {
Collection collection = null;
try {
SpringCloudContractAssertions.assertThat(collection).hasFlattenedSizeGreaterThanOrEqualTo(1);
SpringCloudContractAssertions.assertThat(collection)
.hasFlattenedSizeGreaterThanOrEqualTo(1);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("Expecting actual not to be null");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("Expecting actual not to be null");
}
}
@@ -116,10 +148,13 @@ public class CollectionAssertTests {
Collection collection = nestedCollection();
try {
SpringCloudContractAssertions.assertThat(collection).hasFlattenedSizeLessThanOrEqualTo(1);
SpringCloudContractAssertions.assertThat(collection)
.hasFlattenedSizeLessThanOrEqualTo(1);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("The flattened size <4> is not less or equal to <1>");
}
catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining(
"The flattened size <4> is not less or equal to <1>");
}
}
@@ -128,20 +163,21 @@ public class CollectionAssertTests {
Collection collection = null;
try {
SpringCloudContractAssertions.assertThat(collection).hasFlattenedSizeLessThanOrEqualTo(1);
SpringCloudContractAssertions.assertThat(collection)
.hasFlattenedSizeLessThanOrEqualTo(1);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("Expecting actual not to be null");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("Expecting actual not to be null");
}
}
@Test
public void should_not_throw_an_exception_when_flattened_size_is_between_the_provided_sizes() {
Collection collection = nestedCollection();
SpringCloudContractAssertions.assertThat(collection)
.hasFlattenedSizeBetween(1, 5)
SpringCloudContractAssertions.assertThat(collection).hasFlattenedSizeBetween(1, 5)
.hasFlattenedSizeBetween(4, 4);
}
@@ -150,10 +186,13 @@ public class CollectionAssertTests {
Collection collection = nestedCollection();
try {
SpringCloudContractAssertions.assertThat(collection).hasFlattenedSizeBetween(5, 7);
SpringCloudContractAssertions.assertThat(collection)
.hasFlattenedSizeBetween(5, 7);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("The flattened size <4> is not between <5> and <7>");
}
catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining(
"The flattened size <4> is not between <5> and <7>");
}
}
@@ -162,10 +201,13 @@ public class CollectionAssertTests {
Collection collection = null;
try {
SpringCloudContractAssertions.assertThat(collection).hasFlattenedSizeBetween(1, 2);
SpringCloudContractAssertions.assertThat(collection)
.hasFlattenedSizeBetween(1, 2);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("Expecting actual not to be null");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("Expecting actual not to be null");
}
}
@@ -174,8 +216,7 @@ public class CollectionAssertTests {
Collection collection = collection();
SpringCloudContractAssertions.assertThat(collection)
.hasSizeGreaterThanOrEqualTo(0)
.hasSizeGreaterThanOrEqualTo(3);
.hasSizeGreaterThanOrEqualTo(0).hasSizeGreaterThanOrEqualTo(3);
}
@Test
@@ -183,10 +224,13 @@ public class CollectionAssertTests {
Collection collection = collection();
try {
SpringCloudContractAssertions.assertThat(collection).hasSizeGreaterThanOrEqualTo(5);
SpringCloudContractAssertions.assertThat(collection)
.hasSizeGreaterThanOrEqualTo(5);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("The size <3> is not greater or equal to <5>");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("The size <3> is not greater or equal to <5>");
}
}
@@ -195,10 +239,13 @@ public class CollectionAssertTests {
Collection collection = null;
try {
SpringCloudContractAssertions.assertThat(collection).hasSizeGreaterThanOrEqualTo(1);
SpringCloudContractAssertions.assertThat(collection)
.hasSizeGreaterThanOrEqualTo(1);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("Expecting actual not to be null");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("Expecting actual not to be null");
}
}
@@ -206,8 +253,7 @@ public class CollectionAssertTests {
public void should_not_throw_an_exception_when_size_is_less_than_or_equal_to_provided_size() {
Collection collection = collection();
SpringCloudContractAssertions.assertThat(collection)
.hasSizeLessThanOrEqualTo(4)
SpringCloudContractAssertions.assertThat(collection).hasSizeLessThanOrEqualTo(4)
.hasSizeLessThanOrEqualTo(3);
}
@@ -216,10 +262,13 @@ public class CollectionAssertTests {
Collection collection = collection();
try {
SpringCloudContractAssertions.assertThat(collection).hasSizeLessThanOrEqualTo(1);
SpringCloudContractAssertions.assertThat(collection)
.hasSizeLessThanOrEqualTo(1);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("The size <3> is not less or equal to <1>");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("The size <3> is not less or equal to <1>");
}
}
@@ -228,20 +277,21 @@ public class CollectionAssertTests {
Collection collection = null;
try {
SpringCloudContractAssertions.assertThat(collection).hasSizeLessThanOrEqualTo(1);
SpringCloudContractAssertions.assertThat(collection)
.hasSizeLessThanOrEqualTo(1);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("Expecting actual not to be null");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("Expecting actual not to be null");
}
}
@Test
public void should_not_throw_an_exception_when_size_is_between_the_provided_sizes() {
Collection collection = collection();
SpringCloudContractAssertions.assertThat(collection)
.hasSizeBetween(1, 4)
SpringCloudContractAssertions.assertThat(collection).hasSizeBetween(1, 4)
.hasSizeBetween(3, 3);
}
@@ -252,8 +302,10 @@ public class CollectionAssertTests {
try {
SpringCloudContractAssertions.assertThat(collection).hasSizeBetween(5, 7);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("The size <3> is not between <5> and <7>");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("The size <3> is not between <5> and <7>");
}
}
@@ -262,10 +314,13 @@ public class CollectionAssertTests {
Collection collection = collection();
try {
SpringCloudContractAssertions.assertThat(collection).as("for jsonpath x.y.z").hasSizeBetween(5, 7);
SpringCloudContractAssertions.assertThat(collection).as("for jsonpath x.y.z")
.hasSizeBetween(5, 7);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("[for jsonpath x.y.z] The size <3> is not between <5> and <7>");
}
catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining(
"[for jsonpath x.y.z] The size <3> is not between <5> and <7>");
}
}
@@ -276,8 +331,10 @@ public class CollectionAssertTests {
try {
SpringCloudContractAssertions.assertThat(collection).hasSizeBetween(1, 2);
Assertions.fail("should throw exception");
} catch (AssertionError e) {
Assertions.assertThat(e).hasMessageContaining("Expecting actual not to be null");
}
catch (AssertionError e) {
Assertions.assertThat(e)
.hasMessageContaining("Expecting actual not to be null");
}
}
@@ -312,4 +369,4 @@ public class CollectionAssertTests {
return list;
}
}
}

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder

View File

@@ -1,9 +1,9 @@
package org.springframework.cloud.contract.verifier.builder
import spock.lang.Issue
import spock.lang.Specification
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
import spock.lang.Specification
/**
* @author Marcin Grzejszczak
@@ -20,7 +20,7 @@ class ClassBuilderSpec extends Specification {
def "should return a class from the generated path by taking two last folders when package with base classes is provided"() {
given:
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: 'com.example.base')
String contractRelativeFolder = ['com','example','some','superpackage'].join(File.separator)
String contractRelativeFolder = ['com', 'example', 'some', 'superpackage'].join(File.separator)
expect:
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SomeSuperpackageBase'
}
@@ -28,7 +28,7 @@ class ClassBuilderSpec extends Specification {
def "should return a class from the generated path by taking two last folders when package with base classes is provided and contains invalid chars"() {
given:
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: 'com.example.base')
String contractRelativeFolder = ['com','example','beer-api-producer-external','beer-api-consumer'].join(File.separator)
String contractRelativeFolder = ['com', 'example', 'beer-api-producer-external', 'beer-api-consumer'].join(File.separator)
expect:
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.Beer_api_producer_externalBeer_api_consumerBase'
}
@@ -45,7 +45,7 @@ class ClassBuilderSpec extends Specification {
given:
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(
packageWithBaseClasses: 'com.example.base',
baseClassMappings: ['.*' : 'com.example.base.SuperClass'])
baseClassMappings: ['.*': 'com.example.base.SuperClass'])
String contractRelativeFolder = 'superpackage'
expect:
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperClass'
@@ -55,7 +55,7 @@ class ClassBuilderSpec extends Specification {
def "should match base class when mapping regex has multiple folders"() {
given:
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(
baseClassMappings: ['.*bar.baz.some.*' : 'com.example.base.SuperClass'])
baseClassMappings: ['.*bar.baz.some.*': 'com.example.base.SuperClass'])
String contractRelativeFolder = 'foo/bar/baz/some/package'.split("/").join(File.separator)
expect:
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperClass'
@@ -66,7 +66,7 @@ class ClassBuilderSpec extends Specification {
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(
baseClassForTests: 'a.b.Class',
packageWithBaseClasses: 'com.example.base',
baseClassMappings: ['patternNotMatchingAnything' : 'com.example.base.SuperClass'])
baseClassMappings: ['patternNotMatchingAnything': 'com.example.base.SuperClass'])
String contractRelativeFolder = 'superpackage'
expect:
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperpackageBase'
@@ -75,7 +75,7 @@ class ClassBuilderSpec extends Specification {
def "should return a class from the generated path by when external contracts are picked"() {
given:
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: "foo.Bar")
String contractRelativeFolder = ["org","springframework","cloud","contract","verifier","tests","META_INF","com.example","hello_world","0.1.0_dev.1.uncommitted+d1174dd"].join(File.separator)
String contractRelativeFolder = ["org", "springframework", "cloud", "contract", "verifier", "tests", "META_INF", "com.example", "hello_world", "0.1.0_dev.1.uncommitted+d1174dd"].join(File.separator)
expect:
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'foo.Bar.Hello_world0_1_0_dev_1_uncommitted_d1174ddBase'
}

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder
@@ -28,278 +28,279 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig
*/
class ContractHttpDocsSpec extends Specification {
@Shared ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true)
@Shared
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true)
org.springframework.cloud.contract.spec.Contract httpDsl =
// tag::http_dsl[]
org.springframework.cloud.contract.spec.Contract.make {
// Definition of HTTP request part of the contract
// (this can be a valid request or invalid depending
// on type of contract being specified).
request {
method GET()
url "/foo"
//...
org.springframework.cloud.contract.spec.Contract httpDsl =
// tag::http_dsl[]
org.springframework.cloud.contract.spec.Contract.make {
// Definition of HTTP request part of the contract
// (this can be a valid request or invalid depending
// on type of contract being specified).
request {
method GET()
url "/foo"
//...
}
// Definition of HTTP response part of the contract
// (a service implementing this contract should respond
// with following response after receiving request
// specified in "request" part above).
response {
status 200
//...
}
// Contract priority, which can be used for overriding
// contracts (1 is highest). Priority is optional.
priority 1
}
// Definition of HTTP response part of the contract
// (a service implementing this contract should respond
// with following response after receiving request
// specified in "request" part above).
response {
status 200
//...
}
// Contract priority, which can be used for overriding
// contracts (1 is highest). Priority is optional.
priority 1
}
// end::http_dsl[]
org.springframework.cloud.contract.spec.Contract request =
// tag::request[]
org.springframework.cloud.contract.spec.Contract.make {
request {
// HTTP request method (GET/POST/PUT/DELETE).
method 'GET'
org.springframework.cloud.contract.spec.Contract request =
// tag::request[]
org.springframework.cloud.contract.spec.Contract.make {
request {
// HTTP request method (GET/POST/PUT/DELETE).
method 'GET'
// Path component of request URL is specified as follows.
urlPath('/users')
// Path component of request URL is specified as follows.
urlPath('/users')
}
response {
//...
status 200
}
}
// end::request[]
response {
//...
status 200
org.springframework.cloud.contract.spec.Contract url =
// tag::url[]
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
// Specifying `url` and `urlPath` in one contract is illegal.
url('http://localhost:8888/users')
}
response {
//...
status 200
}
}
}
// end::request[]
// end::url[]
org.springframework.cloud.contract.spec.Contract url =
// tag::url[]
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
org.springframework.cloud.contract.spec.Contract urlPaths =
// tag::urlpath[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
// Specifying `url` and `urlPath` in one contract is illegal.
url('http://localhost:8888/users')
urlPath('/users') {
// Each parameter is specified in form
// `'paramName' : paramValue` where parameter value
// may be a simple literal or one of matcher functions,
// all of which are used in this example.
queryParameters {
// If a simple literal is used as value
// default matcher function is used (equalTo)
parameter 'limit': 100
// `equalTo` function simply compares passed value
// using identity operator (==).
parameter 'filter': equalTo("email")
// `containing` function matches strings
// that contains passed substring.
parameter 'gender': value(consumer(containing("[mf]")), producer('mf'))
// `matching` function tests parameter
// against passed regular expression.
parameter 'offset': value(consumer(matching("[0-9]+")), producer(123))
// `notMatching` functions tests if parameter
// does not match passed regular expression.
parameter 'loginStartsWith': value(consumer(notMatching(".{0,2}")), producer(3))
}
}
//...
}
response {
//...
status 200
}
}
// end::urlpath[]
response {
//...
status 200
org.springframework.cloud.contract.spec.Contract headers =
// tag::headers[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
// Each header is added in form `'Header-Name' : 'Header-Value'`.
// there are also some helper methods
headers {
header 'key': 'value'
contentType(applicationJson())
}
//...
}
response {
//...
status 200
}
}
}
// end::url[]
// end::headers[]
org.springframework.cloud.contract.spec.Contract urlPaths =
// tag::urlpath[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
org.springframework.cloud.contract.spec.Contract cookies =
// tag::cookies[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
urlPath('/users') {
// Each Cookies is added in form `'Cookie-Key' : 'Cookie-Value'`.
// there are also some helper methods
cookies {
cookie 'key': 'value'
cookie('another_key', 'another_value')
}
// Each parameter is specified in form
// `'paramName' : paramValue` where parameter value
// may be a simple literal or one of matcher functions,
// all of which are used in this example.
queryParameters {
//...
}
// If a simple literal is used as value
// default matcher function is used (equalTo)
parameter 'limit': 100
response {
//...
status 200
}
}
// end::cookies[]
// `equalTo` function simply compares passed value
// using identity operator (==).
parameter 'filter': equalTo("email")
org.springframework.cloud.contract.spec.Contract body =
// tag::body[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
// `containing` function matches strings
// that contains passed substring.
parameter 'gender': value(consumer(containing("[mf]")), producer('mf'))
// Currently only JSON format of request body is supported.
// Format will be determined from a header or body's content.
body '''{ "login" : "john", "name": "John The Contract" }'''
}
// `matching` function tests parameter
// against passed regular expression.
parameter 'offset': value(consumer(matching("[0-9]+")), producer(123))
response {
//...
status 200
}
}
// end::body[]
// `notMatching` functions tests if parameter
// does not match passed regular expression.
parameter 'loginStartsWith': value(consumer(notMatching(".{0,2}")), producer(3))
org.springframework.cloud.contract.spec.Contract bodyAsXml =
// tag::bodyAsXml[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
// In this case body will be formatted as XML.
body equalToXml(
'''<user><login>john</login><name>John The Contract</name></user>'''
)
}
response {
//...
status 200
}
}
// end::bodyAsXml[]
org.springframework.cloud.contract.spec.Contract response =
// tag::response[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
}
response {
// Status code sent by the server
// in response to request specified above.
status OK()
}
}
// end::response[]
org.springframework.cloud.contract.spec.Contract regex =
// tag::regex[]
org.springframework.cloud.contract.spec.Contract.make {
request {
method('GET')
url $(consumer(~/\/[0-9]{2}/), producer('/12'))
}
response {
status OK()
body(
id: $(anyNumber()),
surname: $(
consumer('Kowalsky'),
producer(regex('[a-zA-Z]+'))
),
name: 'Jan',
created: $(consumer('2014-02-02 12:23:43'), producer(execute('currentDate(it)'))),
correlationId: value(consumer('5d1f9fef-e0dc-4f3d-a7e4-72d2220dd827'),
producer(regex('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}'))
)
)
headers {
header 'Content-Type': 'text/plain'
}
}
//...
}
// end::regex[]
response {
//...
status 200
}
}
// end::urlpath[]
org.springframework.cloud.contract.spec.Contract headers =
// tag::headers[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
// Each header is added in form `'Header-Name' : 'Header-Value'`.
// there are also some helper methods
headers {
header 'key': 'value'
contentType(applicationJson())
org.springframework.cloud.contract.spec.Contract optionals =
// tag::optionals[]
org.springframework.cloud.contract.spec.Contract.make {
priority 1
request {
method 'POST'
url '/users/password'
headers {
contentType(applicationJson())
}
body(
email: $(consumer(optional(regex(email()))), producer('abc@abc.com')),
callback_url: $(consumer(regex(hostname())), producer('http://partners.com'))
)
}
//...
}
response {
//...
status 200
}
}
// end::headers[]
org.springframework.cloud.contract.spec.Contract cookies =
// tag::cookies[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
// Each Cookies is added in form `'Cookie-Key' : 'Cookie-Value'`.
// there are also some helper methods
cookies {
cookie 'key': 'value'
cookie('another_key', 'another_value')
}
//...
}
response {
//...
status 200
}
}
// end::cookies[]
org.springframework.cloud.contract.spec.Contract body =
// tag::body[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
// Currently only JSON format of request body is supported.
// Format will be determined from a header or body's content.
body '''{ "login" : "john", "name": "John The Contract" }'''
}
response {
//...
status 200
}
}
// end::body[]
org.springframework.cloud.contract.spec.Contract bodyAsXml =
// tag::bodyAsXml[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
// In this case body will be formatted as XML.
body equalToXml(
'''<user><login>john</login><name>John The Contract</name></user>'''
)
}
response {
//...
status 200
}
}
// end::bodyAsXml[]
org.springframework.cloud.contract.spec.Contract response =
// tag::response[]
org.springframework.cloud.contract.spec.Contract.make {
request {
//...
method GET()
url "/foo"
}
response {
// Status code sent by the server
// in response to request specified above.
status OK()
}
}
// end::response[]
org.springframework.cloud.contract.spec.Contract regex =
// tag::regex[]
org.springframework.cloud.contract.spec.Contract.make {
request {
method('GET')
url $(consumer(~/\/[0-9]{2}/), producer('/12'))
}
response {
status OK()
body(
id: $(anyNumber()),
surname: $(
consumer('Kowalsky'),
producer(regex('[a-zA-Z]+'))
),
name: 'Jan',
created: $(consumer('2014-02-02 12:23:43'), producer(execute('currentDate(it)'))),
correlationId: value(consumer('5d1f9fef-e0dc-4f3d-a7e4-72d2220dd827'),
producer(regex('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}'))
)
)
headers {
header 'Content-Type': 'text/plain'
response {
status 404
headers {
header 'Content-Type': 'application/json'
}
body(
code: value(consumer("123123"), producer(optional("123123")))
)
}
}
}
// end::regex[]
org.springframework.cloud.contract.spec.Contract optionals =
// tag::optionals[]
org.springframework.cloud.contract.spec.Contract.make {
priority 1
request {
method 'POST'
url '/users/password'
headers {
contentType(applicationJson())
}
body(
email: $(consumer(optional(regex(email()))), producer('abc@abc.com')),
callback_url: $(consumer(regex(hostname())), producer('http://partners.com'))
)
}
response {
status 404
headers {
header 'Content-Type': 'application/json'
}
body(
code: value(consumer("123123"), producer(optional("123123")))
)
}
}
// end::optionals[]
// end::optionals[]
def 'should convert dsl with optionals to proper Spock test'() {
given:
@@ -308,9 +309,9 @@ class ContractHttpDocsSpec extends Specification {
new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method"))
.appendTo(blockBuilder)
expect:
String expectedTest =
String expectedTest =
// tag::optionals_test[]
"""
"""
given:
def request = given()
.header("Content-Type", "application/json")
@@ -328,35 +329,35 @@ class ContractHttpDocsSpec extends Specification {
assertThatJson(parsedJson).field("['code']").matches("(123123)?")
"""
// end::optionals_test[]
stripped(blockBuilder.toString()) == stripped(expectedTest)
stripped(blockBuilder.toString()) == stripped(expectedTest)
}
org.springframework.cloud.contract.spec.Contract method =
// tag::method[]
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'PUT'
url $(consumer(regex('^/api/[0-9]{2}$')), producer('/api/12'))
headers {
header 'Content-Type': 'application/json'
}
body '''\
org.springframework.cloud.contract.spec.Contract method =
// tag::method[]
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'PUT'
url $(consumer(regex('^/api/[0-9]{2}$')), producer('/api/12'))
headers {
header 'Content-Type': 'application/json'
}
body '''\
[{
"text": "Gonna see you at Warsaw"
}]
'''
}
response {
body(
path: $(consumer('/api/12'), producer(regex('^/api/[0-9]{2}$'))),
correlationId: $(consumer('1223456'), producer(execute('isProperCorrelationId($it)')))
)
status OK()
}
}
response {
body (
path: $(consumer('/api/12'), producer(regex('^/api/[0-9]{2}$'))),
correlationId: $(consumer('1223456'), producer(execute('isProperCorrelationId($it)')))
)
status OK()
}
}
// end::method[]
// end::method[]
private String stripped(String string) {
return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ','')
return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ', '')
}
}

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder
@@ -33,10 +33,12 @@ import org.springframework.cloud.contract.verifier.util.SyntaxChecker
class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStubVerifier {
@Shared ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true)
@Shared GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod(
@Shared
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true)
@Shared
GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod(
new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method")
@Shared
// tag::contract_with_cookies[]
Contract contractDslWithCookiesValue = Contract.make {
@@ -129,9 +131,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
@Issue("#187")
@@ -164,9 +166,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
@Issue("#79")
@@ -201,9 +203,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
@Issue("#79")
@@ -241,9 +243,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
@Issue("#82")
@@ -272,9 +274,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | bodyString
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """entity('{\"items\":[\"HOP\"]}', 'application/json')"""
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("{\\"items\\":[\\"HOP\\"]}", "application/json")'
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("{\\"items\\":[\\"HOP\\"]}", "application/json")'
}
@Issue("#88")
@@ -303,9 +305,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | bodyString
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """entity('property1=VAL1', 'application/octet-stream')"""
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("property1=VAL1", "application/octet-stream")'
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("property1=VAL1", "application/octet-stream")'
}
def "should generate assertions for array in response body with #methodBuilderName"() {
@@ -338,9 +340,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
def "should generate assertions for array inside response body element with #methodBuilderName"() {
@@ -372,9 +374,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
def "should generate assertions for nested objects in response body with #methodBuilderName"() {
@@ -406,9 +408,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
def "should generate regex assertions for map objects in response body with #methodBodyName"() {
@@ -445,9 +447,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
def "should generate regex assertions for string objects in response body with #methodBuilderName"() {
@@ -477,9 +479,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
def "should ignore 'Accept' header and use 'request' method with #methodBuilderName"() {
@@ -507,9 +509,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | requestString
methodBuilderName | methodBuilder | requestString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "request('text/plain')"
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'request("text/plain")'
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'request("text/plain")'
}
def "should ignore 'Content-Type' header and use 'entity' method with #methodBuilderName"() {
@@ -542,9 +544,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | requestStrings
methodBuilderName | methodBuilder | requestStrings
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ["""entity('', 'text/plain')""", """header('Timer', '123')"""]
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['entity("\\"\\"", "text/plain")', 'header("Timer", "123")']
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['entity("\\"\\"", "text/plain")', 'header("Timer", "123")']
}
def "should generate a call with an url path and query parameters with #methodBuilderName"() {
@@ -598,9 +600,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | modifyStringIfRequired
methodBuilderName | methodBuilder | modifyStringIfRequired
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString.replace("'", "\"") }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString.replace("'", "\"") }
}
@Issue('#169')
@@ -655,9 +657,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | modifyStringIfRequired
methodBuilderName | methodBuilder | modifyStringIfRequired
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString.replace("'", "\"") }
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString.replace("'", "\"") }
}
def "should generate test for empty body with #methodBuilderName"() {
@@ -685,9 +687,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | bodyString
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "entity('', 'application/octet-stream')"
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("", "application/octet-stream"'
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("", "application/octet-stream"'
}
def "should not parse the response body if there is no response body specified in the contract"() {
@@ -713,9 +715,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | bodyParsingString
methodBuilderName | methodBuilder | bodyParsingString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "String responseAsString = response.readEntity(String)"
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "String responseAsString = response.readEntity(String.class);"
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "String responseAsString = response.readEntity(String.class);"
}
def "should generate test for String in response body with #methodBodyName"() {
@@ -743,9 +745,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString
methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "String responseAsString = response.readEntity(String)" | 'responseBody == "test"'
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'String responseBody = responseAsString;' | 'assertThat(responseBody).isEqualTo("test");'
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'String responseBody = responseAsString;' | 'assertThat(responseBody).isEqualTo("test");'
}
@Issue('#171')
@@ -778,49 +780,49 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder | methodString
methodBuilderName | methodBuilder | methodString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ".method('GET')"
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'method("GET")'
}
def "should generate a call with an url path and query parameters with JUnit - we'll put it into docs"() {
given:
Contract contractDsl = Contract.make {
request {
method 'GET'
urlPath('/users') {
queryParameters {
parameter 'limit': $(consumer(equalTo("20")), producer(equalTo("10")))
parameter 'offset': $(consumer(containing("20")), producer(equalTo("20")))
parameter 'filter': "email"
parameter 'sort': equalTo("name")
parameter 'search': $(consumer(notMatching(~/^\/[0-9]{2}$/)), producer("55"))
parameter 'age': $(consumer(notMatching("^\\w*\$")), producer("99"))
parameter 'name': $(consumer(matching("Denis.*")), producer("Denis.Stepanov"))
parameter 'email': "bob@email.com"
parameter 'hello': $(consumer(matching("Denis.*")), producer(absent()))
parameter 'hello': absent()
Contract contractDsl = Contract.make {
request {
method 'GET'
urlPath('/users') {
queryParameters {
parameter 'limit': $(consumer(equalTo("20")), producer(equalTo("10")))
parameter 'offset': $(consumer(containing("20")), producer(equalTo("20")))
parameter 'filter': "email"
parameter 'sort': equalTo("name")
parameter 'search': $(consumer(notMatching(~/^\/[0-9]{2}$/)), producer("55"))
parameter 'age': $(consumer(notMatching("^\\w*\$")), producer("99"))
parameter 'name': $(consumer(matching("Denis.*")), producer("Denis.Stepanov"))
parameter 'email': "bob@email.com"
parameter 'hello': $(consumer(matching("Denis.*")), producer(absent()))
parameter 'hello': absent()
}
}
}
}
response {
status OK()
body """
response {
status OK()
body """
{
"property1": "a"
}
"""
}
}
}
MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedResponse =
String expectedResponse =
// tag::jaxrs[]
'''
'''
// when:
Response response = webTarget
.path("/users")
@@ -844,7 +846,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
assertThatJson(parsedJson).field("['property1']").isEqualTo("a");
'''
// end::jaxrs[]
stripped(test) == stripped(expectedResponse)
stripped(test) == stripped(expectedResponse)
and:
stubMappingIsValidWireMockStub(contractDsl)
and:
@@ -1056,26 +1058,26 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
def "should allow c/p version of consumer producer"() {
given:
Contract contractDsl = Contract.make {
request {
method "GET"
url "test"
}
response {
status OK()
body(
property1: "a",
property2: $(
c('123'),
p(regex('[0-9]{3}'))
)
)
headers {
header('Content-Type': 'application/json')
Contract contractDsl = Contract.make {
request {
method "GET"
url "test"
}
response {
status OK()
body(
property1: "a",
property2: $(
c('123'),
p(regex('[0-9]{3}'))
)
)
headers {
header('Content-Type': 'application/json')
}
}
}
}
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
@@ -1102,24 +1104,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
method 'GET'
urlPath '/get'
body([
alpha: $(anyAlphaUnicode()),
number: $(anyNumber()),
positiveInt: $(positiveInt()),
aDouble: $(anyDouble()),
aBoolean: $(aBoolean()),
ip: $(anyIpAddress()),
hostname: $(anyHostname()),
email: $(anyEmail()),
url: $(anyUrl()),
httpsUrl: $(anyHttpsUrl()),
uuid: $(anyUuid()),
date: $(anyDate()),
dateTime: $(anyDateTime()),
time: $(anyTime()),
alpha : $(anyAlphaUnicode()),
number : $(anyNumber()),
positiveInt : $(positiveInt()),
aDouble : $(anyDouble()),
aBoolean : $(aBoolean()),
ip : $(anyIpAddress()),
hostname : $(anyHostname()),
email : $(anyEmail()),
url : $(anyUrl()),
httpsUrl : $(anyHttpsUrl()),
uuid : $(anyUuid()),
date : $(anyDate()),
dateTime : $(anyDateTime()),
time : $(anyTime()),
iso8601WithOffset: $(anyIso8601WithOffset()),
nonBlankString: $(anyNonBlankString()),
nonEmptyString: $(anyNonEmptyString()),
anyOf: $(anyOf('foo', 'bar'))
nonBlankString : $(anyNonBlankString()),
nonEmptyString : $(anyNonEmptyString()),
anyOf : $(anyOf('foo', 'bar'))
])
headers {
contentType(applicationJson())
@@ -1128,24 +1130,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
response {
status OK()
body([
alpha: $(anyAlphaUnicode()),
number: $(anyNumber()),
positiveInt: $(positiveInt()),
aDouble: $(anyDouble()),
aBoolean: $(aBoolean()),
ip: $(anyIpAddress()),
hostname: $(anyHostname()),
email: $(anyEmail()),
url: $(anyUrl()),
httpsUrl: $(anyHttpsUrl()),
uuid: $(anyUuid()),
date: $(anyDate()),
dateTime: $(anyDateTime()),
time: $(anyTime()),
alpha : $(anyAlphaUnicode()),
number : $(anyNumber()),
positiveInt : $(positiveInt()),
aDouble : $(anyDouble()),
aBoolean : $(aBoolean()),
ip : $(anyIpAddress()),
hostname : $(anyHostname()),
email : $(anyEmail()),
url : $(anyUrl()),
httpsUrl : $(anyHttpsUrl()),
uuid : $(anyUuid()),
date : $(anyDate()),
dateTime : $(anyDateTime()),
time : $(anyTime()),
iso8601WithOffset: $(anyIso8601WithOffset()),
nonBlankString: $(anyNonBlankString()),
nonEmptyString: $(anyNonEmptyString()),
anyOf: $(anyOf('foo', 'bar'))
nonBlankString : $(anyNonBlankString()),
nonEmptyString : $(anyNonEmptyString()),
anyOf : $(anyOf('foo', 'bar'))
])
headers {
contentType(applicationJson())
@@ -1187,17 +1189,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
'''
and:
LinkedList<String> lines = [] as LinkedList<String>
test.eachLine { if (it.contains("assertThatJson")) lines << it else it }
test.eachLine {
if (it.contains("assertThatJson")) {
lines << it
}
else {
it
}
}
lines.addFirst(jsonSample)
SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n"))
where:
methodBuilderName | methodBuilder | endOfLineRegexSymbol
"JaxRsClientSpockMethodRequestProcessingBodyBuilder"| { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }| '$'
methodBuilderName | methodBuilder | endOfLineRegexSymbol
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$'
}
private String stripped(String string) {
return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ','')
return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ', '')
}
@Issue('#173')
@@ -1274,8 +1283,8 @@ DATA
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
methodBuilderName | methodBuilder
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
@Issue('#261')
@@ -1307,8 +1316,8 @@ DATA
and:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
where:
methodBuilderName | methodBuilder
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
methodBuilderName | methodBuilder
"JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
}
def "should generate test for cookies with string value in JAX-RS JUnit test"() {

View File

@@ -10,10 +10,12 @@ import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;
* @author Marcin Grzejszczak
*/
public class JsonAssertTests {
// #537
@Test
public void should_compare_big_decimals() {
DocumentContext context = JsonPath.parse("{\"foo\": 55534673.56}");
assertThatJson(context).field("['foo']").isEqualTo(55534673.56);
}
}

View File

@@ -1,55 +1,59 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
import org.springframework.cloud.contract.verifier.util.SyntaxChecker
import spock.lang.Issue
import spock.lang.Shared
import spock.lang.Specification
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
import org.springframework.cloud.contract.verifier.util.SyntaxChecker
/**
* @author Marcin Grzejszczak
* @author Tim Ysewyn
*/
class MessagingMethodBodyBuilderSpec extends Specification {
@Shared ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true, generatedTestSourcesDir: new File("."),
@Shared
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true, generatedTestSourcesDir: new File("."),
generatedTestResourcesDir: new File("."))
@Shared GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod(
@Shared
GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod(
new SingleTestGenerator.GeneratedClassData("foo", "bar", new File("target/test.java").toPath()), "method")
def "should work for triggered based messaging with Spock"() {
given:
// tag::trigger_method_dsl[]
def contractDsl = Contract.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('activemq:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
messagingContentType(applicationJson())
}
}
}
def contractDsl = Contract.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('activemq:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
messagingContentType(applicationJson())
}
}
}
// end::trigger_method_dsl[]
MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod)
BlockBuilder blockBuilder = new BlockBuilder(" ")
@@ -57,9 +61,9 @@ def contractDsl = Contract.make {
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMessage =
String expectedMessage =
// tag::trigger_method_test[]
'''
'''
when:
bookReturnedTriggered()
@@ -74,7 +78,7 @@ def contractDsl = Contract.make {
'''
// end::trigger_method_test[]
stripped(test) == stripped(expectedMessage)
stripped(test) == stripped(expectedMessage)
}
def "should work for triggered based messaging with JUnit"() {
@@ -99,9 +103,9 @@ def contractDsl = Contract.make {
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMessage =
String expectedMessage =
// tag::trigger_method_junit_test[]
'''
'''
// when:
bookReturnedTriggered();
@@ -122,38 +126,38 @@ def contractDsl = Contract.make {
def "should generate tests triggered by a message for Spock"() {
given:
// tag::trigger_message_dsl[]
def contractDsl = Contract.make {
label 'some_label'
input {
messageFrom('jms:input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('jms:output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
// end::trigger_message_dsl[]
// tag::trigger_message_dsl[]
def contractDsl = Contract.make {
label 'some_label'
input {
messageFrom('jms:input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('jms:output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
// end::trigger_message_dsl[]
MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMessage =
String expectedMessage =
// tag::trigger_message_spock[]
"""\
"""\
given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
'''{"bookName":"foo"}''',
@@ -204,9 +208,9 @@ and:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMessage =
String expectedMessage =
// tag::trigger_message_junit[]
'''
'''
// given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
@@ -231,30 +235,30 @@ and:
def "should generate tests without destination, triggered by a message"() {
given:
// tag::trigger_no_output_dsl[]
def contractDsl = Contract.make {
label 'some_label'
input {
messageFrom('jms:delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
// end::trigger_no_output_dsl[]
// tag::trigger_no_output_dsl[]
def contractDsl = Contract.make {
label 'some_label'
input {
messageFrom('jms:delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
// end::trigger_no_output_dsl[]
MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMsg =
String expectedMsg =
// tag::trigger_no_output_spock[]
'''
'''
given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
\'\'\'{"bookName":"foo"}\'\'\',
@@ -293,9 +297,9 @@ then:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMsg =
String expectedMsg =
// tag::trigger_no_output_junit[]
'''
'''
// given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
@@ -338,8 +342,8 @@ then:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMsg =
'''
String expectedMsg =
'''
// given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
@@ -387,8 +391,8 @@ then:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMsg =
"""
String expectedMsg =
"""
given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create('''{"bookName":"foo"}'''
,[
@@ -413,35 +417,35 @@ then:
def "should generate tests without headers for JUnit with consumer / producer notation"() {
given:
def contractDsl =
// tag::consumer_producer[]
Contract.make {
label 'some_label'
input {
messageFrom value(consumer('jms:output'), producer('jms:input'))
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo $(consumer('jms:input'), producer('jms:output'))
body([
bookName: 'foo'
])
}
}
// end::consumer_producer[]
MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod)
BlockBuilder blockBuilder = new BlockBuilder(" ")
def contractDsl =
// tag::consumer_producer[]
Contract.make {
label 'some_label'
input {
messageFrom value(consumer('jms:output'), producer('jms:input'))
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo $(consumer('jms:input'), producer('jms:output'))
body([
bookName: 'foo'
])
}
}
// end::consumer_producer[]
MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
String expectedMsg =
'''
String expectedMsg =
'''
// given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
@@ -457,7 +461,7 @@ Contract.make {
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
'''
stripped(test) == stripped(expectedMsg)
stripped(test) == stripped(expectedMsg)
}
@Issue("336")
@@ -488,7 +492,7 @@ Contract.make {
def test = blockBuilder.toString()
then:
String expectedMsg =
'''
'''
// when:
requestIsCalled();
@@ -501,7 +505,7 @@ Contract.make {
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+");
'''
stripped(test) == stripped(expectedMsg)
stripped(test) == stripped(expectedMsg)
}
@Issue("567")
@@ -520,9 +524,9 @@ Contract.make {
headers {
header('processId', value(producer(regex('\\d+')), consumer('123')))
}
body([
eventId: value(producer(regex('\\d+')), consumer('1'))
])
body([
eventId: value(producer(regex('\\d+')), consumer('1'))
])
}
}
MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod)
@@ -531,7 +535,7 @@ Contract.make {
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
test.contains('assertThat(response.getHeader("processId").toString()).matches("\\\\d+");')
test.contains('assertThat(response.getHeader("processId").toString()).matches("\\\\d+");')
}
@@ -539,36 +543,36 @@ Contract.make {
def "should allow easier way of providing dynamic values for [#methodBuilderName]"() {
given:
//tag::regex_creating_props[]
Contract contractDsl = Contract.make {
label 'trigger_event'
input {
triggeredBy('toString()')
Contract contractDsl = Contract.make {
label 'trigger_event'
input {
triggeredBy('toString()')
}
outputMessage {
sentTo 'topic.rateablequote'
body([
alpha : $(anyAlphaUnicode()),
number : $(anyNumber()),
anInteger : $(anyInteger()),
positiveInt : $(anyPositiveInt()),
aDouble : $(anyDouble()),
aBoolean : $(aBoolean()),
ip : $(anyIpAddress()),
hostname : $(anyHostname()),
email : $(anyEmail()),
url : $(anyUrl()),
httpsUrl : $(anyHttpsUrl()),
uuid : $(anyUuid()),
date : $(anyDate()),
dateTime : $(anyDateTime()),
time : $(anyTime()),
iso8601WithOffset: $(anyIso8601WithOffset()),
nonBlankString : $(anyNonBlankString()),
nonEmptyString : $(anyNonEmptyString()),
anyOf : $(anyOf('foo', 'bar'))
])
}
}
outputMessage {
sentTo 'topic.rateablequote'
body([
alpha: $(anyAlphaUnicode()),
number: $(anyNumber()),
anInteger: $(anyInteger()),
positiveInt: $(anyPositiveInt()),
aDouble: $(anyDouble()),
aBoolean: $(aBoolean()),
ip: $(anyIpAddress()),
hostname: $(anyHostname()),
email: $(anyEmail()),
url: $(anyUrl()),
httpsUrl: $(anyHttpsUrl()),
uuid: $(anyUuid()),
date: $(anyDate()),
dateTime: $(anyDateTime()),
time: $(anyTime()),
iso8601WithOffset: $(anyIso8601WithOffset()),
nonBlankString: $(anyNonBlankString()),
nonEmptyString: $(anyNonEmptyString()),
anyOf: $(anyOf('foo', 'bar'))
])
}
}
//end::regex_creating_props[]
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
@@ -604,7 +608,14 @@ Contract.make {
'''
and:
LinkedList<String> lines = [] as LinkedList<String>
test.eachLine { if (it.contains("assertThatJson")) lines << it else it }
test.eachLine {
if (it.contains("assertThatJson")) {
lines << it
}
else {
it
}
}
lines.addFirst(jsonSample)
lines.addLast('''assertThatJson(parsedJson).field("['shouldFail']").matches("(\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])");''')
String assertionsOnly = lines.join("\n")
@@ -616,7 +627,7 @@ Contract.make {
Exception error = thrown(Exception)
(error.message ? error.message : error.cause.message).contains('''doesn't match the JSON path [$[?(@.['shouldFail'] =~ ''')
where:
methodBuilderName | methodBuilder | endOfLineRegExSymbol
methodBuilderName | methodBuilder | endOfLineRegExSymbol
"SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
"JUnitMessagingMethodBodyBuilder" | { Contract dsl -> new JUnitMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$'
}
@@ -684,7 +695,7 @@ Contract.make {
def test = blockBuilder.toString()
then:
String expectedMsg =
'''
'''
when:
requestIsCalled()
@@ -696,7 +707,7 @@ Contract.make {
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+")
'''
stripped(test) == stripped(expectedMsg)
stripped(test) == stripped(expectedMsg)
}
@Issue("587")
@@ -727,7 +738,7 @@ Contract.make {
def test = blockBuilder.toString()
then:
String expectedMsg =
'''
'''
when:
requestIsCalled()
@@ -739,7 +750,7 @@ Contract.make {
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field("['eventId']").matches("[\\S\\s]+")
'''
stripped(test) == stripped(expectedMsg)
stripped(test) == stripped(expectedMsg)
}
@Issue("440")
@@ -770,7 +781,7 @@ Contract.make {
def test = blockBuilder.toString()
then:
String expectedMsg =
'''
'''
when:
requestIsCalled()
@@ -782,7 +793,7 @@ Contract.make {
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+")
'''
stripped(test) == stripped(expectedMsg)
stripped(test) == stripped(expectedMsg)
}
@Issue("440")
@@ -862,7 +873,7 @@ Contract.make {
!test.contains('REGEXP>>')
test == expectedTest
where:
methodBuilderName | methodBuilder | expectedTest
methodBuilderName | methodBuilder | expectedTest
"SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' when:
foo()
@@ -918,7 +929,7 @@ Contract.make {
!test.contains('REGEXP>>')
test == expectedTest
where:
methodBuilderName | methodBuilder | expectedTest
methodBuilderName | methodBuilder | expectedTest
"SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
fileToBytes(this, "method_request_request.pdf")
@@ -998,7 +1009,7 @@ Contract.make {
!test.contains('REGEXP>>')
test == expectedTest
where:
methodBuilderName | methodBuilder | expectedTest
methodBuilderName | methodBuilder | expectedTest
"SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' when:
createNewPerson()

View File

@@ -36,7 +36,8 @@ class MethodBodyBuilderSpec extends Specification implements WireMockStubVerifie
@Rule
OutputCapture capture = new OutputCapture()
@Shared GeneratedClassDataForMethod classDataForMethod = new GeneratedClassDataForMethod(
@Shared
GeneratedClassDataForMethod classDataForMethod = new GeneratedClassDataForMethod(
new SingleTestGenerator.GeneratedClassData("ClassName", "com.example",
new File("target/test.java").toPath()),
"some_method"
@@ -110,7 +111,12 @@ DocumentContext parsedJson = JsonPath.parse(json);
and:
LinkedList<String> lines = [] as LinkedList<String>
test.eachLine {
if (it.contains("assertThatJson") || it.contains("assertThat((String")) lines << it else it
if (it.contains("assertThatJson") || it.contains("assertThat((String")) {
lines << it
}
else {
it
}
}
lines.addFirst(jsonSample)
SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n"))
@@ -231,7 +237,14 @@ DocumentContext parsedJson = JsonPath.parse(json);
'''
and:
LinkedList<String> lines = [] as LinkedList<String>
test.eachLine { if (it.contains('"foo".equals')) lines << it else it }
test.eachLine {
if (it.contains('"foo".equals')) {
lines << it
}
else {
it
}
}
lines.addFirst(jsonSample)
SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n"))
where:
@@ -278,13 +291,22 @@ DocumentContext parsedJson = JsonPath.parse(json);
'''
and:
LinkedList<String> lines = [] as LinkedList<String>
test.eachLine { if (it.contains('assertThatJson')) lines << it else it }
test.eachLine {
if (it.contains('assertThatJson')) {
lines << it
}
else {
it
}
}
lines.addFirst(jsonSample)
try {
SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n"))
} catch (IllegalStateException e) {
}
catch (IllegalStateException e) {
assert e.message.contains("Parsed JSON [{}] doesn't match the JSON path")
} catch (InvocationTargetException e1) {
}
catch (InvocationTargetException e1) {
assert e1.cause.message.contains("Parsed JSON [{}] doesn't match the JSON path")
}
where:
@@ -364,7 +386,7 @@ DocumentContext parsedJson = JsonPath.parse(json);
SyntaxChecker.tryToCompile(methodBuilderName, test)
asserter(test)
where:
methodBuilderName | methodBuilder | asserter
methodBuilderName | methodBuilder | asserter
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> testBody.contains("response.header('Content-Length') == 4") && testBody.contains("response.header('Content-Type') ==~ java.util.regex.Pattern.compile('application/pdf.*')") }
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> testBody.contains('assertThat(response.header("Content-Length")).isEqualTo(4);') && testBody.contains('assertThat(response.header("Content-Type")).matches("application/pdf.*");') }
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> testBody.contains("response.getHeaderString('Content-Length') == 4") && testBody.contains(" response.getHeaderString('Content-Type') ==~ java.util.regex.Pattern.compile('application/pdf.*')") }
@@ -466,7 +488,7 @@ DocumentContext parsedJson = JsonPath.parse(json);
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | responseAsserter
methodBuilderName | methodBuilder | responseAsserter
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> string.contains('responseBody == "My name"') }
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> string.contains('assertThat(responseBody).isEqualTo("My name");') }
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> string.contains('responseBody == "My name"') }
@@ -1187,8 +1209,8 @@ DocumentContext parsedJson = JsonPath.parse(json);
body(
[
content: [
one: "two",
two: "two",
one : "two",
two : "two",
three: [
six: "seven"
]
@@ -1213,10 +1235,53 @@ DocumentContext parsedJson = JsonPath.parse(json);
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) }
"MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) }
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) }
}
@Issue("#727")
def "should not leave empty arrays in a simple structure [#methodBuilderName]"() {
given:
Contract contractDsl = Contract.make {
request {
method 'GET'
url '/list'
}
response {
status 200
body(
[
content: [
three: [
six: "seven"
]
]
]
)
bodyMatchers {
jsonPath('$.content.three.six', byRegex(".*seven.*"))
jsonPath('$.content.one', byRegex(".*two.*"))
}
}
}
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
String test = blockBuilder.toString()
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test)
!test.contains('''.isEmpty()''')
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) }
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) }
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) }
}
}

View File

@@ -1,35 +1,36 @@
package org.springframework.cloud.contract.verifier.builder
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.file.ContractMetadata
import spock.lang.Issue
import spock.lang.Specification
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.file.ContractMetadata
class MethodBuilderSpec extends Specification {
@Issue('#518')
def "should map create valid method name from file name containing illegal chars"() {
given:
Contract contractDsl = Contract.make {
request {
method 'GET'
urlPath '/foo'
}
response {
status OK()
body(foo: "foo")
headers {
contentType(applicationJson())
}
}
}
ContractMetadata metadata = new ContractMetadata(null, false, 0, null, contractDsl)
when:
File stubFile = new File("invalid-method:name.groovy")
@Issue('#518')
def "should map create valid method name from file name containing illegal chars"() {
given:
Contract contractDsl = Contract.make {
request {
method 'GET'
urlPath '/foo'
}
response {
status OK()
body(foo: "foo")
headers {
contentType(applicationJson())
}
}
}
ContractMetadata metadata = new ContractMetadata(null, false, 0, null, contractDsl)
when:
File stubFile = new File("invalid-method:name.groovy")
String methodName = MethodBuilder.methodName(metadata, stubFile, contractDsl)
then:
methodName == "invalid_method_name"
}
String methodName = MethodBuilder.methodName(metadata, stubFile, contractDsl)
then:
methodName == "invalid_method_name"
}
}

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder
@@ -37,7 +37,8 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
assertJsonSize: true
)
@Shared GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod(
@Shared
GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod(
new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method")
@Issue('#185')
@@ -200,13 +201,14 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
and:
try {
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString())
} catch (ClassFormatError classFormatError) {
}
catch (ClassFormatError classFormatError) {
String output = outputCapture.toString()
assert output.contains('error: cannot find symbol')
assert output.contains('assertThatValueIsANumber(parsedJson.read("$.duck"));')
}
where:
methodBuilderName | methodBuilder | rootElement
methodBuilderName | methodBuilder | rootElement
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$'
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
@@ -272,11 +274,12 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
and:
try {
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString())
} catch (NoClassDefFoundError error) {
}
catch (NoClassDefFoundError error) {
// that's actually expected since we're creating an anonymous class
}
where:
methodBuilderName | methodBuilder | rootElement
methodBuilderName | methodBuilder | rootElement
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$'
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
@@ -327,11 +330,12 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
and:
try {
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString())
} catch (NoClassDefFoundError error) {
}
catch (NoClassDefFoundError error) {
// that's actually expected since we're creating an anonymous class
}
where:
methodBuilderName | methodBuilder | rootElement
methodBuilderName | methodBuilder | rootElement
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$'
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
@@ -367,7 +371,7 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
then:
test.contains('foo(parsedJson.read("' + rootElement + '.phoneNumbers[*].number")')
where:
methodBuilderName | methodBuilder | rootElement
methodBuilderName | methodBuilder | rootElement
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$'
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
@@ -403,7 +407,7 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
IllegalStateException e = thrown(IllegalStateException)
e.message.contains('Entry for the provided JSON path <$.nonExistingPhoneNumbers[*].number> doesn\'t exist in the body')
where:
methodBuilderName | methodBuilder | rootElement
methodBuilderName | methodBuilder | rootElement
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$'
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
@@ -443,7 +447,7 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
then:
test.contains('assertThat(parsedJson.read("' + rootElement + '[0][0].access_token", String.class)).isEqualTo("123")')
where:
methodBuilderName | methodBuilder | rootElement
methodBuilderName | methodBuilder | rootElement
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$'
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$'

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder
@@ -24,7 +24,6 @@ import spock.lang.Specification
import org.springframework.cloud.contract.verifier.TestGenerator
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
import org.springframework.cloud.contract.verifier.config.TestFramework
import org.springframework.cloud.contract.verifier.config.TestMode
import org.springframework.cloud.contract.verifier.file.ContractMetadata
import org.springframework.cloud.contract.verifier.util.SyntaxChecker
import org.springframework.util.FileSystemUtils
@@ -52,10 +51,10 @@ class SingleTestGeneratorSpec extends Specification {
'import com.jayway.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
private static final List<String> mockMvcJUnitRestAssured3ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;',
'import org.junit.FixMethodOrder;', 'import org.junit.Ignore;', 'import org.junit.Test;', 'import org.junit.runners.MethodSorters;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;',
'@FixMethodOrder(MethodSorters.NAME_ASCENDING)', '@Test', '@Ignore', 'import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;',
'import io.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
'import org.junit.FixMethodOrder;', 'import org.junit.Ignore;', 'import org.junit.Test;', 'import org.junit.runners.MethodSorters;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;',
'@FixMethodOrder(MethodSorters.NAME_ASCENDING)', '@Test', '@Ignore', 'import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;',
'import io.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
private static final List<String> explicitJUnitRestAssured2ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;',
'import org.junit.FixMethodOrder;', 'import org.junit.Ignore;', 'import org.junit.Test;', 'import org.junit.runners.MethodSorters;',
@@ -71,30 +70,30 @@ class SingleTestGeneratorSpec extends Specification {
private static
final List<String> mockMvcJUnit5RestAssured2ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;',
'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*;',
'@Test', '@Disabled', 'import com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification;',
'import com.jayway.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*;',
'@Test', '@Disabled', 'import com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification;',
'import com.jayway.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
private static
final List<String> mockMvcJUnit5RestAssured3ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;',
'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;',
'@Test', '@Disabled', 'import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;',
'import io.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;',
'@Test', '@Disabled', 'import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;',
'import io.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
private static
final List<String> explicitJUnit5RestAssured2ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;',
'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static com.jayway.restassured.RestAssured.*;',
'@Test', '@Disabled', 'import com.jayway.restassured.specification.RequestSpecification;',
'import com.jayway.restassured.response.Response;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static com.jayway.restassured.RestAssured.*;',
'@Test', '@Disabled', 'import com.jayway.restassured.specification.RequestSpecification;',
'import com.jayway.restassured.response.Response;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
private static
final List<String> explicitJUnit5RestAssured3ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;',
'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static io.restassured.RestAssured.*;',
'@Test', '@Disabled', 'import io.restassured.specification.RequestSpecification;',
'import io.restassured.response.Response;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static io.restassured.RestAssured.*;',
'@Test', '@Disabled', 'import io.restassured.specification.RequestSpecification;',
'import io.restassured.response.Response;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat']
private static final List<String> spockClassRestAssured2Strings = ['import com.jayway.jsonpath.DocumentContext', 'import com.jayway.jsonpath.JsonPath',
@@ -226,7 +225,7 @@ class SingleTestGeneratorSpec extends Specification {
def "should build test class for #testFramework with Rest Assured 2x"() {
given:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testFramework =testFramework
properties.testFramework = testFramework
properties.testMode = mode
ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, order,
convertAsCollection(new File('/'), file))
@@ -278,7 +277,7 @@ class SingleTestGeneratorSpec extends Specification {
}
''')
and:
File file2 = tmpFolder.newFile()
File file2 = tmpFolder.newFile()
file2.write('''
org.springframework.cloud.contract.spec.Contract.make {
request {
@@ -299,7 +298,7 @@ class SingleTestGeneratorSpec extends Specification {
''')
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testFramework =testFramework
properties.testFramework = testFramework
ContractMetadata contract = new ContractMetadata(file.toPath(), false, 1, null,
convertAsCollection(new File('/'), file))
contract.ignored >> false
@@ -320,20 +319,20 @@ class SingleTestGeneratorSpec extends Specification {
and:
textAssertion(clazz)
where:
testFramework | mode | classStrings | asserter | textAssertion
JUNIT | MOCKMVC | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2}
JUNIT | EXPLICIT | explicitJUnitRestAssured3ClassStrings | JAVA_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2}
JUNIT5 | MOCKMVC | mockMvcJUnit5RestAssured3ClassStrings | JAVA_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2}
JUNIT5 | EXPLICIT | explicitJUnit5RestAssured3ClassStrings | JAVA_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2}
SPOCK | MOCKMVC | spockClassRestAssured3Strings | GROOVY_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tdef request') == 2}
SPOCK | EXPLICIT | explicitSpockRestAssured2ClassStrings | GROOVY_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tdef request') == 2}
testFramework | mode | classStrings | asserter | textAssertion
JUNIT | MOCKMVC | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2 }
JUNIT | EXPLICIT | explicitJUnitRestAssured3ClassStrings | JAVA_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2 }
JUNIT5 | MOCKMVC | mockMvcJUnit5RestAssured3ClassStrings | JAVA_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2 }
JUNIT5 | EXPLICIT | explicitJUnit5RestAssured3ClassStrings | JAVA_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2 }
SPOCK | MOCKMVC | spockClassRestAssured3Strings | GROOVY_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tdef request') == 2 }
SPOCK | EXPLICIT | explicitSpockRestAssured2ClassStrings | GROOVY_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tdef request') == 2 }
}
def 'should build JaxRs test class for #testFramework'() {
given:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testMode = JAXRSCLIENT
properties.testFramework =testFramework
properties.testFramework = testFramework
ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, null, convertAsCollection(new File('/'), file))
contract.ignored >> true
JavaTestGenerator testGenerator = new JavaTestGenerator()
@@ -375,7 +374,7 @@ class SingleTestGeneratorSpec extends Specification {
''')
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testFramework =testFramework
properties.testFramework = testFramework
ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, order, convertAsCollection(new File('/'), file))
contract.ignored >> true
and:
@@ -419,7 +418,7 @@ class SingleTestGeneratorSpec extends Specification {
''')
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testFramework =testFramework
properties.testFramework = testFramework
and:
ContractMetadata contract2 = new ContractMetadata(secondFile.toPath(), true, 1, order, convertAsCollection(new File('/'), file))
contract2.ignored >> false
@@ -484,7 +483,7 @@ class SingleTestGeneratorSpec extends Specification {
''')
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testFramework =JUNIT
properties.testFramework = JUNIT
properties.testMode = EXPLICIT
properties.baseClassForTests = 'test.ContextPathTestingBaseClass'
and:
@@ -580,7 +579,7 @@ class SingleTestGeneratorSpec extends Specification {
}''')
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testFramework =testFramework
properties.testFramework = testFramework
ContractMetadata contract = new ContractMetadata(secondFile.toPath(), false, 1, null, convertAsCollection(new File('/'), secondFile))
JavaTestGenerator testGenerator = new JavaTestGenerator()
when:
@@ -600,9 +599,9 @@ class SingleTestGeneratorSpec extends Specification {
File temp = tmpFolder.newFolder()
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
basePackageForTests: 'a.b',
generatedTestSourcesDir: temp,
generatedTestSourcesDir: temp,
generatedTestResourcesDir: tmpFolder.newFolder()
)
TestGenerator testGenerator = new TestGenerator(properties)
@@ -626,7 +625,7 @@ class SingleTestGeneratorSpec extends Specification {
File temp = tmpFolder.newFolder()
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
basePackageForTests: 'a.b', generatedTestSourcesDir: temp,
generatedTestResourcesDir: tmpFolder.newFolder()
)
@@ -651,7 +650,7 @@ class SingleTestGeneratorSpec extends Specification {
File temp = tmpFolder.newFolder()
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
baseClassForTests: 'a.b.SomeClass', generatedTestSourcesDir: temp,
generatedTestResourcesDir: tmpFolder.newFolder()
)
@@ -676,7 +675,7 @@ class SingleTestGeneratorSpec extends Specification {
File temp = tmpFolder.newFolder()
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
packageWithBaseClasses: 'a.b', generatedTestSourcesDir: temp,
generatedTestResourcesDir: tmpFolder.newFolder()
)
@@ -701,8 +700,8 @@ class SingleTestGeneratorSpec extends Specification {
File temp = tmpFolder.newFolder()
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
generatedTestSourcesDir: temp, generatedTestResourcesDir: tmpFolder.newFolder()
testFramework: testFramework, contractsDslDir: contractLocation.parentFile,
generatedTestSourcesDir: temp, generatedTestResourcesDir: tmpFolder.newFolder()
)
TestGenerator testGenerator = new TestGenerator(properties)
when:
@@ -720,7 +719,7 @@ class SingleTestGeneratorSpec extends Specification {
def 'should throw exception in JUnit5 when contract belongs to scenario'() {
given:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testFramework =JUNIT5
properties.testFramework = JUNIT5
properties.testMode = mode
ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 1, convertAsCollection(new File('/'), file))
JavaTestGenerator testGenerator = new JavaTestGenerator()

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2018-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder
@@ -54,19 +54,19 @@ class XmlMethodBodyBuilderSpec extends Specification {
Contract contractDsl =
// tag::xmlgroovy[]
Contract.make {
request {
method GET()
urlPath '/get'
headers {
contentType(applicationXml())
}
}
response {
status(OK())
headers {
contentType(applicationXml())
}
body """
request {
method GET()
urlPath '/get'
headers {
contentType(applicationXml())
}
}
response {
status(OK())
headers {
contentType(applicationXml())
}
body """
<test>
<duck type='xtype'>123</duck>
<alpha>abc</alpha>
@@ -83,22 +83,22 @@ class XmlMethodBodyBuilderSpec extends Specification {
<valueWithoutAMatcher>foo</valueWithoutAMatcher>
<key><complex>foo</complex></key>
</test>"""
bodyMatchers {
xPath('/test/duck/text()', byRegex("[0-9]{3}"))
xPath('/test/duck/text()', byCommand('test($it)'))
xPath('/test/duck/xxx', byNull())
xPath('/test/duck/text()', byEquality())
xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode()))
xPath('/test/alpha/text()', byEquality())
xPath('/test/number/text()', byRegex(number()))
xPath('/test/date/text()', byDate())
xPath('/test/dateTime/text()', byTimestamp())
xPath('/test/time/text()', byTime())
xPath('/test/*/complex/text()', byEquality())
xPath('/test/duck/@type', byEquality())
bodyMatchers {
xPath('/test/duck/text()', byRegex("[0-9]{3}"))
xPath('/test/duck/text()', byCommand('test($it)'))
xPath('/test/duck/xxx', byNull())
xPath('/test/duck/text()', byEquality())
xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode()))
xPath('/test/alpha/text()', byEquality())
xPath('/test/number/text()', byRegex(number()))
xPath('/test/date/text()', byDate())
xPath('/test/dateTime/text()', byTimestamp())
xPath('/test/time/text()', byTime())
xPath('/test/*/complex/text()', byEquality())
xPath('/test/duck/@type', byEquality())
}
}
}
}
}
// end::xmlgroovy[]
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(' ')

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.converter
@@ -19,7 +19,8 @@ package org.springframework.cloud.contract.verifier.converter
import spock.lang.Specification
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.spec.Contract
/**
* @author Marcin Grzejszczak
* @author Tim Ysewyn
@@ -552,8 +553,8 @@ class DslToYamlContractConverterSpec extends Specification {
yamlContract.request.method == 'GET'
yamlContract.request.url == '/get'
yamlContract.request.body.replaceAll("\n", "")
.replaceAll(' ', '') == xmlContractBody.replaceAll("\n", "")
.replaceAll(' ', '')
.replaceAll(' ', '') == xmlContractBody.replaceAll("\n", "")
.replaceAll(' ', '')
yamlContract.request.headers == [
"Content-Type": "application/xml"
]
@@ -565,12 +566,12 @@ class DslToYamlContractConverterSpec extends Specification {
]
yamlContract.response.status == 200
yamlContract.response.body.replaceAll("\n", "")
.replaceAll(' ', '') == xmlContractBody.replaceAll("\n", "")
.replaceAll(' ', '')
.replaceAll(' ', '') == xmlContractBody.replaceAll("\n", "")
.replaceAll(' ', '')
yamlContract.response.matchers.body == [
new YamlContract.BodyTestMatcher(
path: '/test/duck/xxx',
type: YamlContract.TestMatcherType.by_null)
]
}
}
}

View File

@@ -1,23 +1,24 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.converter
import java.util.regex.Pattern
import groovy.json.JsonSlurper
import spock.lang.Issue
import spock.lang.Shared
import spock.lang.Specification
@@ -49,12 +50,18 @@ import static org.springframework.cloud.contract.spec.internal.MatchingType.TYPE
*/
class YamlContractConverterSpec extends Specification {
@Shared URL ymlUrl = YamlContractConverterSpec.getResource("/yml/contract.yml")
@Shared File ymlWithRest = new File(ymlUrl.toURI())
@Shared URL ymlUrl2 = YamlContractConverterSpec.getResource("/yml/contract_rest.yml")
@Shared File ymlWithRest2 = new File(ymlUrl2.toURI())
@Shared URL ymlUrl3 = YamlContractConverterSpec.getResource("/yml/contract_rest_with_path.yml")
@Shared File ymlWithRest3 = new File(ymlUrl3.toURI())
@Shared
URL ymlUrl = YamlContractConverterSpec.getResource("/yml/contract.yml")
@Shared
File ymlWithRest = new File(ymlUrl.toURI())
@Shared
URL ymlUrl2 = YamlContractConverterSpec.getResource("/yml/contract_rest.yml")
@Shared
File ymlWithRest2 = new File(ymlUrl2.toURI())
@Shared
URL ymlUrl3 = YamlContractConverterSpec.getResource("/yml/contract_rest_with_path.yml")
@Shared
File ymlWithRest3 = new File(ymlUrl3.toURI())
URL ymlMsgUrl = YamlContractConverterSpec.getResource("/yml/contract_message.yml")
File ymlMessaging = new File(ymlMsgUrl.toURI())
URL ymlMsgMethodUrl = YamlContractConverterSpec.getResource("/yml/contract_message_method.yml")
@@ -118,14 +125,24 @@ class YamlContractConverterSpec extends Specification {
contract.request.method.clientValue == "PUT"
contract.request.url.clientValue == "/foo"
contract.request.cookies.entries.find { it.key == "foo" && it.serverValue == "bar" }
contract.request.cookies.entries.find { it.key == "fooRegex" && ((Pattern) it.clientValue).pattern == "reg" && it.serverValue == "reg" }
contract.request.cookies.entries.find { it.key == "fooPredefinedRegex" && ((Pattern) it.clientValue).pattern == "(true|false)" && it.serverValue == true }
contract.request.cookies.entries.find {
it.key == "fooRegex" && ((Pattern) it.clientValue).pattern == "reg" && it.serverValue == "reg"
}
contract.request.cookies.entries.find {
it.key == "fooPredefinedRegex" && ((Pattern) it.clientValue).pattern == "(true|false)" && it.serverValue == true
}
and:
contract.response.status.clientValue == 200
contract.response.cookies.entries.find { it.key == "foo" && it.clientValue == "baz" }
contract.response.cookies.entries.find { it.key == "fooRegex" && ((Pattern) it.serverValue).pattern == "[0-9]+" && it.clientValue == 123 }
contract.response.cookies.entries.find { it.key == "source" && ((Pattern) it.serverValue).pattern == "ip_address" && it.clientValue == "ip_address" }
contract.response.cookies.entries.find { it.key == "fooPredefinedRegex" && ((Pattern) it.serverValue).pattern == "(true|false)" && it.clientValue == true }
contract.response.cookies.entries.find {
it.key == "fooRegex" && ((Pattern) it.serverValue).pattern == "[0-9]+" && it.clientValue == 123
}
contract.response.cookies.entries.find {
it.key == "source" && ((Pattern) it.serverValue).pattern == "ip_address" && it.clientValue == "ip_address"
}
contract.response.cookies.entries.find {
it.key == "fooPredefinedRegex" && ((Pattern) it.serverValue).pattern == "(true|false)" && it.clientValue == true
}
contract.response.body.clientValue == ["status": "OK"]
}
@@ -149,23 +166,38 @@ class YamlContractConverterSpec extends Specification {
url.queryParameters.parameters[1].name == "b"
url.queryParameters.parameters[1].serverValue == "c"
contract.request.method.clientValue == "PUT"
contract.request.headers.entries.find { it.name == "foo" &&
((Pattern) it.clientValue).pattern == "bar" && it.serverValue == "bar" }
contract.request.headers.entries.find { it.name == "fooReq" &&
it.serverValue == "baz" }
contract.request.headers.entries.find {
it.name == "foo" &&
((Pattern) it.clientValue).pattern == "bar" && it.serverValue == "bar"
}
contract.request.headers.entries.find {
it.name == "fooReq" &&
it.serverValue == "baz"
}
contract.request.body.clientValue == [foo: "bar"]
contract.request.bodyMatchers.matchers[0].path() == '$.foo'
contract.request.bodyMatchers.matchers[0].matchingType() == REGEX
contract.request.bodyMatchers.matchers[0].value().pattern() == 'bar'
and:
contract.response.status.clientValue == 200
if (yamlFile == ymlWithRest) contract.response.delay.clientValue == 1000 else !contract.response.delay
contract.response.headers.entries.find { it.name == "foo2" &&
((Pattern) it.serverValue).pattern == "bar" && it.clientValue == "bar" }
contract.response.headers.entries.find { it.name == "foo3" &&
((ExecutionProperty) it.serverValue).insertValue('foo') == "andMeToo(foo)" }
contract.response.headers.entries.find { it.name == "fooRes" &&
it.clientValue == "baz" }
if (yamlFile == ymlWithRest) {
contract.response.delay.clientValue == 1000
}
else {
!contract.response.delay
}
contract.response.headers.entries.find {
it.name == "foo2" &&
((Pattern) it.serverValue).pattern == "bar" && it.clientValue == "bar"
}
contract.response.headers.entries.find {
it.name == "foo3" &&
((ExecutionProperty) it.serverValue).insertValue('foo') == "andMeToo(foo)"
}
contract.response.headers.entries.find {
it.name == "fooRes" &&
it.clientValue == "baz"
}
contract.response.body.clientValue == [foo2: "bar", foo3: "baz", nullValue: null]
contract.response.bodyMatchers.matchers[0].path() == '$.foo2'
contract.response.bodyMatchers.matchers[0].matchingType() == REGEX
@@ -226,8 +258,10 @@ class YamlContractConverterSpec extends Specification {
contracts.size() == 1
Contract contract = contracts.first()
RegexPatterns patterns = new RegexPatterns()
contract.request.headers.entries.find { it.name == "Content-Type" &&
((Pattern) it.clientValue).pattern == "application/json.*" && it.serverValue == "application/json" }
contract.request.headers.entries.find {
it.name == "Content-Type" &&
((Pattern) it.clientValue).pattern == "application/json.*" && it.serverValue == "application/json"
}
((Pattern) contract.request.urlPath.clientValue).pattern() == "/get/[0-9]"
contract.request.urlPath.serverValue == "/get/1"
contract.request.urlPath.queryParameters.parameters.size() == 8
@@ -284,7 +318,9 @@ class YamlContractConverterSpec extends Specification {
contract.request.bodyMatchers.matchers[12].minTypeOccurrence() == 1
contract.request.bodyMatchers.matchers[12].maxTypeOccurrence() == 3
contract.request.cookies.entries.find { it.key == "foo" }.clientValue instanceof Pattern
contract.request.cookies.entries.find { it.key == "bar" }.serverValue == new ExecutionProperty('equals($it)')
contract.request.cookies.entries.find {
it.key == "bar"
}.serverValue == new ExecutionProperty('equals($it)')
and:
contract.response.status.clientValue == 200
contract.response.bodyMatchers.matchers[0].path() == '$.duck'
@@ -336,14 +372,16 @@ class YamlContractConverterSpec extends Specification {
}
protected Object assertQueryParam(QueryParameters queryParameters, String queryParamName, Object serverValue,
MatchingStrategy.Type clientType, Object clientValue) {
MatchingStrategy.Type clientType, Object clientValue) {
if (clientType == MatchingStrategy.Type.ABSENT) {
return ! queryParameters.parameters.find { it.name == queryParamName}
return !queryParameters.parameters.find { it.name == queryParamName }
}
return queryParameters.parameters.find {
it.name == queryParamName &&
it.serverValue == serverValue &&
((MatchingStrategy) it.clientValue).type == clientType &&
((MatchingStrategy) it.clientValue).clientValue == clientValue
}
return queryParameters.parameters.find { it.name == queryParamName &&
it.serverValue == serverValue &&
((MatchingStrategy) it.clientValue).type == clientType &&
((MatchingStrategy) it.clientValue).clientValue == clientValue }
}
@Issue("#604")
@@ -356,8 +394,10 @@ class YamlContractConverterSpec extends Specification {
contracts.size() == 1
Contract contract = contracts.first()
RegexPatterns patterns = new RegexPatterns()
contract.input.messageHeaders.entries.find { it.name == "contentType" &&
((Pattern) it.clientValue).pattern == "application/json.*" && it.serverValue == "application/json" }
contract.input.messageHeaders.entries.find {
it.name == "contentType" &&
((Pattern) it.clientValue).pattern == "application/json.*" && it.serverValue == "application/json"
}
contract.input.bodyMatchers.matchers[0].path() == '$.duck'
contract.input.bodyMatchers.matchers[0].matchingType() == REGEX
contract.input.bodyMatchers.matchers[0].value().pattern() == '[0-9]{3}'
@@ -442,9 +482,11 @@ class YamlContractConverterSpec extends Specification {
then:
contracts.size() == 1
Contract contract = contracts.first()
contract.request.body.clientValue == '''{ "hello" : "request" }'''
new JsonSlurper().parseText(contract.request.body.clientValue.toString()) ==
new JsonSlurper().parseText('''{ "hello" : "request" }''')
and:
contract.response.body.clientValue == '''{ "hello" : "response" }'''
new JsonSlurper().parseText(contract.response.body.clientValue.toString()) ==
new JsonSlurper().parseText('''{ "hello" : "response" }''')
}
def "should convert YAML with REST with multipart"() {
@@ -488,20 +530,28 @@ class YamlContractConverterSpec extends Specification {
contract.input.assertThat.toString() == "bar()"
contract.input.messageFrom.serverValue == "foo"
contract.input.triggeredBy.toString() == "foo()"
contract.input.messageHeaders.entries.find { it.name == "foo" &&
((Pattern) it.clientValue).pattern == "bar" && it.serverValue == "bar" }
contract.input.messageHeaders.entries.find {
it.name == "foo" &&
((Pattern) it.clientValue).pattern == "bar" && it.serverValue == "bar"
}
contract.input.messageBody.clientValue == [foo: "bar"]
contract.input.bodyMatchers.matchers[0].path() == '$.bar'
contract.input.bodyMatchers.matchers[0].matchingType() == REGEX
contract.input.bodyMatchers.matchers[0].value().pattern() == 'bar'
and:
contract.outputMessage.assertThat.toString() == "baz()"
contract.outputMessage.headers.entries.find { it.name == "foo2" &&
((Pattern) it.serverValue).pattern == "bar" && it.clientValue == "bar" }
contract.outputMessage.headers.entries.find { it.name == "foo3" &&
((ExecutionProperty) it.serverValue).insertValue('foo') == "andMeToo(foo)" }
contract.outputMessage.headers.entries.find { it.name == "fooRes" &&
it.clientValue == "baz" }
contract.outputMessage.headers.entries.find {
it.name == "foo2" &&
((Pattern) it.serverValue).pattern == "bar" && it.clientValue == "bar"
}
contract.outputMessage.headers.entries.find {
it.name == "foo3" &&
((ExecutionProperty) it.serverValue).insertValue('foo') == "andMeToo(foo)"
}
contract.outputMessage.headers.entries.find {
it.name == "fooRes" &&
it.clientValue == "baz"
}
contract.outputMessage.body.clientValue == [foo2: "bar", foo3: "baz"]
contract.outputMessage.bodyMatchers.matchers[0].path() == '$.foo2'
contract.outputMessage.bodyMatchers.matchers[0].matchingType() == REGEX
@@ -525,7 +575,8 @@ class YamlContractConverterSpec extends Specification {
and:
contract.outputMessage.sentTo.clientValue == "output"
contract.outputMessage.headers.entries.find {
it.name == "BOOK-NAME" && it.clientValue == "foo" }
it.name == "BOOK-NAME" && it.clientValue == "foo"
}
contract.outputMessage.body.clientValue == [bookName: "foo"]
}
@@ -540,13 +591,16 @@ class YamlContractConverterSpec extends Specification {
contract.description == "Some description"
contract.label == "some_label"
contract.input.messageFrom.serverValue == "input"
contract.input.messageHeaders.entries.find { it.name == "sample" &&
it.serverValue == "header" }
contract.input.messageHeaders.entries.find {
it.name == "sample" &&
it.serverValue == "header"
}
contract.input.messageBody.clientValue == [bookName: "foo"]
and:
contract.outputMessage.sentTo.clientValue == "output"
contract.outputMessage.headers.entries.find {
it.name == "BOOK-NAME" && it.clientValue == "foo" }
it.name == "BOOK-NAME" && it.clientValue == "foo"
}
contract.outputMessage.body.clientValue == [bookName: "foo"]
}
@@ -704,15 +758,15 @@ ignored: false
'''
when:
Map<String, byte[]> strings = converter.store([
new YamlContract(
new YamlContract(
name: "post1",
request: new YamlContract.Request(method: "POST", url: "/users/1"),
response: new YamlContract.Response(status: 200)
),new YamlContract(
name: "post2",
request: new YamlContract.Request(method: "POST", url: "/users/2"),
response: new YamlContract.Response(status: 200)
),
), new YamlContract(
name: "post2",
request: new YamlContract.Request(method: "POST", url: "/users/2"),
response: new YamlContract.Response(status: 200)
),
])
then:
strings.size() == 2
@@ -730,7 +784,7 @@ ignored: false
and:
contracts.first().input != null || contracts.first().outputMessage != null
where:
file << [1,2,3].collect {
file << [1, 2, 3].collect {
new File(YamlContractConverterSpec.getResource("/yml/contract_message_scenario${it}.yml").toURI())
}
}
@@ -801,7 +855,7 @@ ignored: false
header("BOOK-NAME", "foo")
}
}
},Contract.make {
}, Contract.make {
input {
description("Some description2")
label("some_label2")
@@ -932,16 +986,16 @@ ignored: false
input {
messageFrom("input")
messageBody([
duck: 123,
alpha: "abc",
number: 123,
aBoolean: true,
date: "2017-01-01",
dateTime: "2017-01-01T01:23:45",
time: "01:02:34",
duck : 123,
alpha : "abc",
number : 123,
aBoolean : true,
date : "2017-01-01",
dateTime : "2017-01-01T01:23:45",
time : "01:02:34",
valueWithoutAMatcher: "foo",
valueWithTypeMatch: "string",
key: ["complex.key": 'foo']
valueWithTypeMatch : "string",
key : ["complex.key": 'foo']
])
bodyMatchers {
jsonPath('$.duck', byRegex("[0-9]{3}"))
@@ -962,22 +1016,22 @@ ignored: false
}
outputMessage {
sentTo("channel")
body([duck: 123,
alpha: "abc",
number: 123,
aBoolean: true,
date: "2017-01-01",
dateTime: "2017-01-01T01:23:45",
time: "01:02:34",
body([duck : 123,
alpha : "abc",
number : 123,
aBoolean : true,
date : "2017-01-01",
dateTime : "2017-01-01T01:23:45",
time : "01:02:34",
valueWithoutAMatcher: "foo",
valueWithTypeMatch: "string",
valueWithMin: [1, 2, 3],
valueWithMax: [1, 2, 3],
valueWithMinMax: [1, 2, 3],
valueWithMinEmpty: [],
valueWithMaxEmpty: [],
key: ['complex.key' : 'foo'],
nullValue: null
valueWithTypeMatch : "string",
valueWithMin : [1, 2, 3],
valueWithMax : [1, 2, 3],
valueWithMinMax : [1, 2, 3],
valueWithMinEmpty : [],
valueWithMaxEmpty : [],
key : ['complex.key': 'foo'],
nullValue : null
])
bodyMatchers {
// asserts the jsonpath value against manual regex
@@ -1040,23 +1094,23 @@ ignored: false
yamlContract.label == "card_rejected"
yamlContract.input.messageFrom == "input"
yamlContract.input.messageBody == [
duck: 123,
alpha: "abc",
number: 123,
aBoolean: true,
date: "2017-01-01",
dateTime: "2017-01-01T01:23:45",
time: "01:02:34",
duck : 123,
alpha : "abc",
number : 123,
aBoolean : true,
date : "2017-01-01",
dateTime : "2017-01-01T01:23:45",
time : "01:02:34",
valueWithoutAMatcher: "foo",
valueWithTypeMatch: "string",
key: ["complex.key": 'foo']
valueWithTypeMatch : "string",
key : ["complex.key": 'foo']
]
yamlContract.input.messageHeaders == [
sample: 'foo',
sample : 'foo',
contentType: "application/json"
]
yamlContract.input.matchers.headers == [
new YamlContract.KeyValueMatcher(
new YamlContract.KeyValueMatcher(
key: "sample", regex: "foo.*")
]
yamlContract.input.matchers.body == [
@@ -1096,23 +1150,23 @@ ignored: false
type: YamlContract.StubMatcherType.by_equality),
]
yamlContract.outputMessage.sentTo == "channel"
yamlContract.outputMessage.body == [duck: 123,
alpha: "abc",
number: 123,
aBoolean: true,
date: "2017-01-01",
dateTime: "2017-01-01T01:23:45",
time: "01:02:34",
yamlContract.outputMessage.body == [duck : 123,
alpha : "abc",
number : 123,
aBoolean : true,
date : "2017-01-01",
dateTime : "2017-01-01T01:23:45",
time : "01:02:34",
valueWithoutAMatcher: "foo",
valueWithTypeMatch: "string",
valueWithMin: [1, 2, 3],
valueWithMax: [1, 2, 3],
valueWithMinMax: [1, 2, 3],
valueWithMinEmpty: [],
valueWithMaxEmpty: [],
key: ['complex.key' : 'foo'],
nullValue: null
]
valueWithTypeMatch : "string",
valueWithMin : [1, 2, 3],
valueWithMax : [1, 2, 3],
valueWithMinMax : [1, 2, 3],
valueWithMinEmpty : [],
valueWithMaxEmpty : [],
key : ['complex.key': 'foo'],
nullValue : null
]
yamlContract.outputMessage.headers == [
"contentType": "application/json",
"Some-Header": "someValue"
@@ -1267,4 +1321,4 @@ ignored: false
.replaceAll(' ', '') == xmlContractBody
.replaceAll("\n", "").replaceAll(' ', '')
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.dsl.wiremock
import com.github.tomakehurst.wiremock.extension.Extension

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.dsl.wiremock
@@ -2535,4 +2535,4 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie
.header("Content-Type", "application/json;charset=UTF-8")
.body(JsonOutput.toJson([["Programming", "Java"], ["Programming", "Java", "Spring", "Boot"]])), String.class).body
}
}
}

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.dsl.wiremock
@@ -35,7 +35,7 @@ class WireMockResponseStubStrategySpec extends Specification {
response {
status irrelevantStatus
body([
value: 1.5
value: 1.5
])
}
}
@@ -58,10 +58,10 @@ class WireMockResponseStubStrategySpec extends Specification {
response {
status irrelevantStatus
body([
number: anyNumber(),
integer: anyInteger(),
positiveInt: anyPositiveInt(),
double: anyDouble(),
number : anyNumber(),
integer : anyInteger(),
positiveInt: anyPositiveInt(),
double : anyDouble(),
])
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.dsl.wiremock
import spock.lang.Specification

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.dsl.wiremock

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2018-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.dsl.wiremock
@@ -211,7 +211,7 @@ class WireMockXmlStubStrategySpec extends Specification implements WireMockStubV
then:
stubMappingIsValidWireMockStub(wireMockStub)
wireMockStub.replaceAll("\n", '').replaceAll(' ', '')
.contains("""
.contains("""
matchesXPath" : {
"expression" : "/test/duck/text()",
"matches" : "[0-9]{3}"
@@ -304,8 +304,8 @@ class WireMockXmlStubStrategySpec extends Specification implements WireMockStubV
then:
stubMappingIsValidWireMockStub(wireMockStub)
wireMockStub.replaceAll("\n", "")
.replaceAll(' ', '')
.contains("""
.replaceAll(' ', '')
.contains("""
"bodyPatterns" : [ {
"matchesXPath": {
"expression": "/test/alpha/text()",

View File

@@ -1,17 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.file

View File

@@ -1,33 +1,51 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.messaging.amqp
import spock.lang.Specification
import org.springframework.amqp.core.Message
import org.springframework.amqp.core.MessageBuilder
import org.springframework.amqp.core.MessagePropertiesBuilder
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage
import spock.lang.Specification
import static org.springframework.amqp.core.MessageProperties.CONTENT_TYPE_JSON
/**
* @author Mathias Düsterhöft
*/
class ContractVerifierHelperSpec extends Specification {
def "should convert message"() {
given:
String payload = '''{"name":"some"}'''
Message message = MessageBuilder
.withBody(payload.bytes)
.andProperties(MessagePropertiesBuilder.newInstance()
.setHeader("my-header", "some")
.setContentType(CONTENT_TYPE_JSON)
.build()).build()
ContractVerifierHelper contractVerifierHelper = new ContractVerifierHelper(null, new Jackson2JsonMessageConverter())
when:
ContractVerifierMessage contractVerifierMessage = contractVerifierHelper.convert(message)
then:
((Map) contractVerifierMessage.payload).containsKey("name")
contractVerifierMessage.headers.containsKey("contentType")
contractVerifierMessage.headers.containsKey("my-header")
}
def "should convert message"() {
given:
String payload = '''{"name":"some"}'''
Message message = MessageBuilder
.withBody(payload.bytes)
.andProperties(MessagePropertiesBuilder.newInstance()
.setHeader("my-header", "some")
.setContentType(CONTENT_TYPE_JSON)
.build()).build()
ContractVerifierHelper contractVerifierHelper = new ContractVerifierHelper(null, new Jackson2JsonMessageConverter())
when:
ContractVerifierMessage contractVerifierMessage = contractVerifierHelper.convert(message)
then:
((Map) contractVerifierMessage.payload).containsKey("name")
contractVerifierMessage.headers.containsKey("contentType")
contractVerifierMessage.headers.containsKey("my-header")
}
}

View File

@@ -1,89 +1,106 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.messaging.amqp
import spock.lang.Specification
import org.springframework.amqp.core.Binding
import org.springframework.amqp.core.BindingBuilder
import org.springframework.amqp.core.DirectExchange
import org.springframework.amqp.core.Queue
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer
import spock.lang.Specification
class MessageListenerAccessorSpec extends Specification {
String queueName = "test.queue"
String exchange = "test-exchange"
SimpleMessageListenerContainer listenerContainer
Binding binding
String queueName = "test.queue"
String exchange = "test-exchange"
SimpleMessageListenerContainer listenerContainer
Binding binding
def "should get single simple listener container"(){
given:
givenSimpleMessageListenerContainer()
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, null)
then:
listenerContainersForDestination.size() == 1
listenerContainersForDestination.get(0) == this.listenerContainer
}
def "should get single simple listener container"() {
given:
givenSimpleMessageListenerContainer()
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, null)
then:
listenerContainersForDestination.size() == 1
listenerContainersForDestination.get(0) == this.listenerContainer
}
def "should get single simple listener container for matching routing key"(){
given:
givenSimpleMessageListenerContainer()
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, '#')
then:
listenerContainersForDestination.size() == 1
listenerContainersForDestination.get(0) == this.listenerContainer
}
def "should get single simple listener container for matching routing key"() {
given:
givenSimpleMessageListenerContainer()
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, '#')
then:
listenerContainersForDestination.size() == 1
listenerContainersForDestination.get(0) == this.listenerContainer
}
def "should get empty simple listener container for non matching routing key"(){
given:
givenSimpleMessageListenerContainer()
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, 'not matching')
then:
listenerContainersForDestination.isEmpty()
}
def "should get empty simple listener container for non matching routing key"() {
given:
givenSimpleMessageListenerContainer()
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, 'not matching')
then:
listenerContainersForDestination.isEmpty()
}
def "should get empty listener container list for unknown destination"(){
given:
givenSimpleMessageListenerContainer()
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination("some-exchange", null)
then:
listenerContainersForDestination.isEmpty()
}
def "should get empty listener container list for unknown destination"() {
given:
givenSimpleMessageListenerContainer()
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination("some-exchange", null)
then:
listenerContainersForDestination.isEmpty()
}
def "should get empty listener container list for queue with no matching listener"(){
given:
givenSimpleMessageListenerContainer()
this.binding = BindingBuilder.bind(new Queue("some.queue")).to(new DirectExchange(this.exchange)).with("#")
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, null)
then:
listenerContainersForDestination.isEmpty()
}
def "should get empty listener container list for queue with no matching listener"() {
given:
givenSimpleMessageListenerContainer()
this.binding = BindingBuilder.bind(new Queue("some.queue")).to(new DirectExchange(this.exchange)).with("#")
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [this.listenerContainer], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, null)
then:
listenerContainersForDestination.isEmpty()
}
def "should get single simple listener container from RabbitListenerEndpointRegistry"(){
given:
givenSimpleMessageListenerContainer()
RabbitListenerEndpointRegistry rabbitListenerEndpointRegistryMock = Mock(RabbitListenerEndpointRegistry)
rabbitListenerEndpointRegistryMock.getListenerContainers() >> [this.listenerContainer]
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(rabbitListenerEndpointRegistryMock, [], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, null)
then:
listenerContainersForDestination.size() == 1
listenerContainersForDestination.get(0) == this.listenerContainer
}
def "should get single simple listener container from RabbitListenerEndpointRegistry"() {
given:
givenSimpleMessageListenerContainer()
RabbitListenerEndpointRegistry rabbitListenerEndpointRegistryMock = Mock(RabbitListenerEndpointRegistry)
rabbitListenerEndpointRegistryMock.getListenerContainers() >> [this.listenerContainer]
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(rabbitListenerEndpointRegistryMock, [], [this.binding])
when:
List<SimpleMessageListenerContainer> listenerContainersForDestination = messageListenerAccessor.getListenerContainersForDestination(this.exchange, null)
then:
listenerContainersForDestination.size() == 1
listenerContainersForDestination.get(0) == this.listenerContainer
}
def givenSimpleMessageListenerContainer() {
this.listenerContainer = new SimpleMessageListenerContainer()
this.listenerContainer.setQueueNames(this.queueName)
this.binding = BindingBuilder.bind(new Queue(this.queueName)).to(new DirectExchange(this.exchange)).with("#")
}
}
def givenSimpleMessageListenerContainer() {
this.listenerContainer = new SimpleMessageListenerContainer()
this.listenerContainer.setQueueNames(this.queueName)
this.binding = BindingBuilder.bind(new Queue(this.queueName)).to(new DirectExchange(this.exchange)).with("#")
}
}

View File

@@ -1,7 +1,25 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.messaging.amqp
import org.mockito.exceptions.verification.WantedButNotInvoked
import spock.lang.Specification
import wiremock.com.google.common.collect.ImmutableMap
import org.springframework.amqp.core.Binding
import org.springframework.amqp.core.BindingBuilder
import org.springframework.amqp.core.DirectExchange
@@ -11,88 +29,88 @@ import org.springframework.amqp.core.Queue
import org.springframework.amqp.rabbit.core.RabbitTemplate
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter
import spock.lang.Specification
import static org.mockito.Mockito.mock
import static org.springframework.amqp.core.MessageProperties.CONTENT_TYPE_JSON
import static org.springframework.amqp.support.converter.DefaultClassMapper.DEFAULT_CLASSID_FIELD_NAME
/**
* @author Mathias Düsterhöft
*/
class SpringAmqpStubMessagesSpec extends Specification {
RabbitTemplate rabbitTemplate = mock(RabbitTemplate.class)
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer()
MessageListenerAdapter messageListenerAdapter = Mock(MessageListenerAdapter.class)
Message message = Mock(Message.class)
RabbitTemplate rabbitTemplate = mock(RabbitTemplate.class)
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer()
MessageListenerAdapter messageListenerAdapter = Mock(MessageListenerAdapter.class)
Message message = Mock(Message.class)
String queueName = "test.queue"
String exchange = "test-exchange"
String payload = '''{"name":"some"}'''
String routingKey = "resource.created"
String queueName = "test.queue"
String exchange = "test-exchange"
String payload = '''{"name":"some"}'''
String routingKey = "resource.created"
def "should send amqp message with type id"() {
given:
listenerContainer.setMessageListener(messageListenerAdapter)
listenerContainer.setQueueNames(queueName)
Binding binding = BindingBuilder.bind(new Queue(queueName)).to(new DirectExchange(exchange)).with(routingKey)
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [listenerContainer], [binding])
SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAccessor)
def "should send amqp message with type id"() {
given:
listenerContainer.setMessageListener(messageListenerAdapter)
listenerContainer.setQueueNames(queueName)
Binding binding = BindingBuilder.bind(new Queue(queueName)).to(new DirectExchange(exchange)).with(routingKey)
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [listenerContainer], [binding])
SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAccessor)
when:
messageVerifier.send(payload,
ImmutableMap.builder()
.put(DEFAULT_CLASSID_FIELD_NAME, "org.example.Some")
.put("amqp_receivedRoutingKey", routingKey)
.put("contentType", CONTENT_TYPE_JSON)
.build(),
exchange)
then:
1 * messageListenerAdapter.onMessage({ Message msg ->
msg.getMessageProperties().getReceivedRoutingKey() == "resource.created" &&
msg.getMessageProperties().getContentType() == CONTENT_TYPE_JSON &&
msg.getMessageProperties().getHeaders().get(DEFAULT_CLASSID_FIELD_NAME) == "org.example.Some"
})
}
when:
messageVerifier.send(payload,
ImmutableMap.builder()
.put(DEFAULT_CLASSID_FIELD_NAME, "org.example.Some")
.put("amqp_receivedRoutingKey", routingKey)
.put("contentType", CONTENT_TYPE_JSON)
.build(),
exchange)
then:
1 * messageListenerAdapter.onMessage({ Message msg ->
msg.getMessageProperties().getReceivedRoutingKey() == "resource.created" &&
msg.getMessageProperties().getContentType() == CONTENT_TYPE_JSON &&
msg.getMessageProperties().getHeaders().get(DEFAULT_CLASSID_FIELD_NAME) == "org.example.Some"
})
}
def "should fail to receive a message if rabbit template wasn't called"() {
given:
listenerContainer.setMessageListener(messageListenerAdapter)
listenerContainer.setQueueNames(queueName)
Binding binding = BindingBuilder.bind(new Queue(queueName)).to(new DirectExchange(exchange)).with(routingKey)
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [listenerContainer], [binding])
SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAccessor)
when:
messageVerifier.receive("foo")
then:
thrown(WantedButNotInvoked)
}
def "should fail to receive a message if rabbit template wasn't called"() {
given:
listenerContainer.setMessageListener(messageListenerAdapter)
listenerContainer.setQueueNames(queueName)
Binding binding = BindingBuilder.bind(new Queue(queueName)).to(new DirectExchange(exchange)).with(routingKey)
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [listenerContainer], [binding])
SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAccessor)
when:
messageVerifier.receive("foo")
then:
thrown(WantedButNotInvoked)
}
def "should return null if received called and message was sent without any body"() {
given:
listenerContainer.setMessageListener(messageListenerAdapter)
listenerContainer.setQueueNames(queueName)
Binding binding = BindingBuilder.bind(new Queue(queueName)).to(new DirectExchange(exchange)).with(routingKey)
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [listenerContainer], [binding])
SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAccessor)
def "should return null if received called and message was sent without any body"() {
given:
listenerContainer.setMessageListener(messageListenerAdapter)
listenerContainer.setQueueNames(queueName)
Binding binding = BindingBuilder.bind(new Queue(queueName)).to(new DirectExchange(exchange)).with(routingKey)
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [listenerContainer], [binding])
SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAccessor)
and:
rabbitTemplate.send("foo", "bar", null, null)
expect:
messageVerifier.receive("foo") == null
}
and:
rabbitTemplate.send("foo", "bar", null, null)
expect:
messageVerifier.receive("foo") == null
}
def "should return match the message if received called and message was sent with a message with null payload"() {
given:
listenerContainer.setMessageListener(messageListenerAdapter)
listenerContainer.setQueueNames(queueName)
Binding binding = BindingBuilder.bind(new Queue(queueName)).to(new DirectExchange(exchange)).with(routingKey)
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [listenerContainer], [binding])
SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAccessor)
message.getMessageProperties() >> new MessageProperties()
and:
rabbitTemplate.send("foo", "bar", message, null)
expect:
messageVerifier.receive("foo") is message
}
def "should return match the message if received called and message was sent with a message with null payload"() {
given:
listenerContainer.setMessageListener(messageListenerAdapter)
listenerContainer.setQueueNames(queueName)
Binding binding = BindingBuilder.bind(new Queue(queueName)).to(new DirectExchange(exchange)).with(routingKey)
MessageListenerAccessor messageListenerAccessor = new MessageListenerAccessor(null, [listenerContainer], [binding])
SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAccessor)
message.getMessageProperties() >> new MessageProperties()
and:
rabbitTemplate.send("foo", "bar", message, null)
expect:
messageVerifier.receive("foo") is message
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.messaging.camel
import org.apache.camel.CamelContext

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.messaging.internal

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.messaging.stream
import spock.lang.Specification

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.messaging.stream
import spock.lang.Issue
@@ -20,7 +36,7 @@ class StreamStubMessagesSpec extends Specification {
ApplicationContext applicationContext = Mock(ApplicationContext)
BindingServiceProperties properties = new BindingServiceProperties(
bindings: [
input: new BindingProperties(destination: "verifications"),
input : new BindingProperties(destination: "verifications"),
output: new BindingProperties(destination: "verifications"),
]
)
@@ -42,7 +58,7 @@ class StreamStubMessagesSpec extends Specification {
ApplicationContext applicationContext = Mock(ApplicationContext)
BindingServiceProperties properties = new BindingServiceProperties(
bindings: [
input: new BindingProperties(destination: "verifications"),
input : new BindingProperties(destination: "verifications"),
output: new BindingProperties(destination: "verifications"),
]
)
@@ -79,8 +95,8 @@ class StreamStubMessagesSpec extends Specification {
then:
1 * applicationContext.getBean("foo", MessageChannel) >> channel
where:
messageInteraction << [ { StreamStubMessages stream -> stream.send("foo", [:], "verifications")},
{ StreamStubMessages stream -> stream.receive("verifications")}]
messageInteraction << [{ StreamStubMessages stream -> stream.send("foo", [:], "verifications") },
{ StreamStubMessages stream -> stream.receive("verifications") }]
}
def "should resolve channel via channel name for send and receive"() {
@@ -103,8 +119,8 @@ class StreamStubMessagesSpec extends Specification {
then:
1 * applicationContext.getBean("verifications", MessageChannel) >> channel
where:
messageInteraction << [ { StreamStubMessages stream -> stream.send("foo", [:], "verifications")},
{ StreamStubMessages stream -> stream.receive("verifications")}]
messageInteraction << [{ StreamStubMessages stream -> stream.send("foo", [:], "verifications") },
{ StreamStubMessages stream -> stream.receive("verifications") }]
}
@Issue("694")
@@ -113,7 +129,7 @@ class StreamStubMessagesSpec extends Specification {
ApplicationContext applicationContext = Mock(ApplicationContext)
BindingServiceProperties properties = new BindingServiceProperties(
bindings: [
input: new BindingProperties(destination: "verificationsChannel"),
input : new BindingProperties(destination: "verificationsChannel"),
output: new BindingProperties(destination: "verificationsChannel"),
]
)
@@ -135,7 +151,7 @@ class StreamStubMessagesSpec extends Specification {
ApplicationContext applicationContext = Mock(ApplicationContext)
BindingServiceProperties properties = new BindingServiceProperties(
bindings: [
input: new BindingProperties(destination: "verificationsChannel"),
input : new BindingProperties(destination: "verificationsChannel"),
output: new BindingProperties(destination: "verificationsChannel"),
]
)
@@ -172,8 +188,8 @@ class StreamStubMessagesSpec extends Specification {
then:
1 * applicationContext.getBean("foo", MessageChannel) >> channel
where:
messageInteraction << [ { StreamStubMessages stream -> stream.send("foo", [:], "verificationsChannel")},
{ StreamStubMessages stream -> stream.receive("verificationsChannel")}]
messageInteraction << [{ StreamStubMessages stream -> stream.send("foo", [:], "verificationsChannel") },
{ StreamStubMessages stream -> stream.receive("verificationsChannel") }]
}
def "should resolve channel via channel name for send and receive and channel name is camel case"() {
@@ -196,7 +212,7 @@ class StreamStubMessagesSpec extends Specification {
then:
1 * applicationContext.getBean("verificationsChannel", MessageChannel) >> channel
where:
messageInteraction << [ { StreamStubMessages stream -> stream.send("foo", [:], "verificationsChannel")},
{ StreamStubMessages stream -> stream.receive("verificationsChannel")}]
messageInteraction << [{ StreamStubMessages stream -> stream.send("foo", [:], "verificationsChannel") },
{ StreamStubMessages stream -> stream.receive("verificationsChannel") }]
}
}

View File

@@ -1,5 +1,22 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.util
import org.springframework.cloud.contract.spec.internal.DslProperty
import spock.lang.Specification
import org.xml.sax.helpers.DefaultHandler

View File

@@ -1,24 +1,25 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.util
import org.springframework.cloud.contract.spec.Contract
import spock.lang.Specification
import org.springframework.cloud.contract.spec.Contract
/**
* @author Marcin Grzejszczak
*/
@@ -111,28 +112,28 @@ class ContractVerifierDslConverterSpec extends Specification {
def "should convert file to a list of Contracts"() {
when:
List<Contract> contract = ContractVerifierDslConverter.convertAsCollection(new File("/"),multipleContracts)
List<Contract> contract = ContractVerifierDslConverter.convertAsCollection(new File("/"), multipleContracts)
then:
contract == expectedMultipleContracts
}
def "should convert text to a list of Contracts"() {
when:
Collection<Contract> contract = ContractVerifierDslConverter.convertAsCollection(new File("/"),multipleContracts.text)
Collection<Contract> contract = ContractVerifierDslConverter.convertAsCollection(new File("/"), multipleContracts.text)
then:
contract == expectedMultipleContractsForText
}
def "should throw an exception when an invalid file is parsed"() {
when:
ContractVerifierDslConverter.convertAsCollection(new File("/"),invalidContract.text)
ContractVerifierDslConverter.convertAsCollection(new File("/"), invalidContract.text)
then:
thrown(DslParseException)
}
def "should throw an exception with file path when an invalid file is parsed"() {
when:
ContractVerifierDslConverter.convertAsCollection(new File("/"),invalidContract)
ContractVerifierDslConverter.convertAsCollection(new File("/"), invalidContract)
then:
DslParseException e = thrown(DslParseException)
e.toString().contains("contract.yml")
@@ -140,7 +141,7 @@ class ContractVerifierDslConverterSpec extends Specification {
def "should throw an exception when a non existent file is parsed"() {
when:
ContractVerifierDslConverter.convertAsCollection(new File("/"),new File("/foo/bar/baz.foo"))
ContractVerifierDslConverter.convertAsCollection(new File("/"), new File("/foo/bar/baz.foo"))
then:
DslParseException e = thrown(DslParseException)
e.cause instanceof FileNotFoundException
@@ -148,14 +149,14 @@ class ContractVerifierDslConverterSpec extends Specification {
def "should convert file to a list of Contracts when there's only one declared contract"() {
when:
Collection<Contract> contract = ContractVerifierDslConverter.convertAsCollection(new File("/"),singleContract)
Collection<Contract> contract = ContractVerifierDslConverter.convertAsCollection(new File("/"), singleContract)
then:
contract == [expectedSingleContract]
}
def "should convert text to a list of Contracts when there's only one declared contract"() {
when:
Collection<Contract> contract = ContractVerifierDslConverter.convertAsCollection(new File("/"),singleContract.text)
Collection<Contract> contract = ContractVerifierDslConverter.convertAsCollection(new File("/"), singleContract.text)
then:
contract == [expectedSingleContractForText]
}

View File

@@ -1,21 +1,23 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.util
import java.util.regex.Pattern
import com.jayway.jsonpath.Configuration
import com.jayway.jsonpath.DocumentContext
import com.jayway.jsonpath.JsonPath
@@ -24,12 +26,11 @@ import com.toomuchcoding.jsonassert.JsonAssertion
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import net.minidev.json.JSONArray
import org.springframework.cloud.contract.spec.internal.BodyMatcher
import org.springframework.cloud.contract.spec.internal.MatchingType
import spock.lang.Specification
import spock.util.environment.RestoreSystemProperties
import java.util.regex.Pattern
import org.springframework.cloud.contract.spec.internal.BodyMatcher
import org.springframework.cloud.contract.spec.internal.MatchingType
class JsonToJsonPathsConverterSpec extends Specification {
@@ -39,23 +40,23 @@ class JsonToJsonPathsConverterSpec extends Specification {
then:
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" &&
it.jsonPath() == '''$[*].['some'].['nested'][?(@.['json'] == 'with value')]'''
it.jsonPath() == '''$[*].['some'].['nested'][?(@.['json'] == 'with value')]'''
}
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" &&
it.jsonPath() == '''$[*].['some'].['nested'][?(@.['anothervalue'] == 4)]'''
it.jsonPath() == '''$[*].['some'].['nested'][?(@.['anothervalue'] == 4)]'''
}
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" &&
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]'''
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]'''
}
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" &&
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]'''
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]'''
}
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").field("['anothernested']").field("['name']").isEqualTo("name3")""" &&
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*].['anothernested'][?(@.['name'] == 'name3')]'''
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*].['anothernested'][?(@.['name'] == 'name3')]'''
}
and:
assertThatJsonPathsInMapAreValid(json, pathAndValues)
@@ -86,7 +87,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
}
]
''',
'''
'''
[{
"someother" : {
"nested" : {
@@ -110,7 +111,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
}
}
]''']
}
}
def 'should convert a json with a map as root to a map of path to value'() {
given:
@@ -130,25 +131,25 @@ class JsonToJsonPathsConverterSpec extends Specification {
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method() == """.field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" &&
it.jsonPath() == '''$.['some'].['nested'][?(@.['json'] == 'with value')]'''
}
pathAndValues.find {
it.method() == """.field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" &&
it.jsonPath() == '''$.['some'].['nested'][?(@.['anothervalue'] == 4)]'''
}
pathAndValues.find {
it.method() == """.field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" &&
it.jsonPath() == '''$.['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]'''
}
pathAndValues.find {
it.method() == """.field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" &&
it.jsonPath() == '''$.['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]'''
}
pathAndValues.find {
it.method() == """.field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" &&
it.jsonPath() == '''$.['some'].['nested'][?(@.['json'] == 'with value')]'''
}
pathAndValues.find {
it.method() == """.field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" &&
it.jsonPath() == '''$.['some'].['nested'][?(@.['anothervalue'] == 4)]'''
}
pathAndValues.find {
it.method() == """.field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" &&
it.jsonPath() == '''$.['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]'''
}
pathAndValues.find {
it.method() == """.field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" &&
it.jsonPath() == '''$.['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]'''
}
and:
assertThatJsonPathsInMapAreValid(json, pathAndValues)
}
}
def 'should convert a json with a list'() {
given:
@@ -162,11 +163,11 @@ class JsonToJsonPathsConverterSpec extends Specification {
then:
pathAndValues.find {
it.method() == """.array("['items']").arrayField().isEqualTo("HOP").value()""" &&
it.jsonPath() == '''$.['items'][?(@ == 'HOP')]'''
it.jsonPath() == '''$.['items'][?(@ == 'HOP')]'''
}
and:
assertThatJsonPathsInMapAreValid(json, pathAndValues)
}
}
def 'should convert a json with null and boolean values'() {
given:
@@ -181,11 +182,11 @@ class JsonToJsonPathsConverterSpec extends Specification {
then:
pathAndValues.find {
it.method() == """.field("['property1']").isNull()""" &&
it.jsonPath() == '''$[?(@.['property1'] == null)]'''
it.jsonPath() == '''$[?(@.['property1'] == null)]'''
}
pathAndValues.find {
it.method() == """.field("['property2']").isEqualTo(true)""" &&
it.jsonPath() == '''$[?(@.['property2'] == true)]'''
it.jsonPath() == '''$[?(@.['property2'] == true)]'''
}
}
@@ -200,15 +201,15 @@ class JsonToJsonPathsConverterSpec extends Specification {
then:
pathAndValues.find {
it.method() == """.field("['extensions']").field("['7']").isEqualTo(28.00)""" &&
it.jsonPath() == '''$.['extensions'][?(@.['7'] == 28.00)]'''
it.jsonPath() == '''$.['extensions'][?(@.['7'] == 28.00)]'''
}
pathAndValues.find {
it.method() == """.field("['extensions']").field("['14']").isEqualTo(41.00)""" &&
it.jsonPath() == '''$.['extensions'][?(@.['14'] == 41.00)]'''
it.jsonPath() == '''$.['extensions'][?(@.['14'] == 41.00)]'''
}
pathAndValues.find {
it.method() == """.field("['extensions']").field("['30']").isEqualTo(60.00)""" &&
it.jsonPath() == '''$.['extensions'][?(@.['30'] == 60.00)]'''
it.jsonPath() == '''$.['extensions'][?(@.['30'] == 60.00)]'''
}
and:
assertThatJsonPathsInMapAreValid(json, pathAndValues)
@@ -229,28 +230,28 @@ class JsonToJsonPathsConverterSpec extends Specification {
then:
pathAndValues.find {
it.method() == """.array("['errors']").contains("['property']").isEqualTo("email")""" &&
it.jsonPath() == '''$.['errors'][*][?(@.['property'] == 'email')]'''
it.jsonPath() == '''$.['errors'][*][?(@.['property'] == 'email')]'''
}
pathAndValues.find {
it.method() == """.array("['errors']").contains("['message']").isEqualTo("inconsistent value")""" &&
it.jsonPath() == '''$.['errors'][*][?(@.['message'] == 'inconsistent value')]'''
it.jsonPath() == '''$.['errors'][*][?(@.['message'] == 'inconsistent value')]'''
}
pathAndValues.find {
it.method() == """.array("['errors']").contains("['message']").isEqualTo("inconsistent value2")""" &&
it.jsonPath() == '''$.['errors'][*][?(@.['message'] == 'inconsistent value2')]'''
it.jsonPath() == '''$.['errors'][*][?(@.['message'] == 'inconsistent value2')]'''
}
and:
assertThatJsonPathsInMapAreValid(json, pathAndValues)
}
}
def 'should convert a map json with a regex pattern'() {
given:
List json = [
[some:
[nested: [
json: "with value",
json : "with value",
anothervalue: 4,
withlist:
withlist :
[
[name: "name2"],
[name: "name1"],
@@ -264,9 +265,9 @@ class JsonToJsonPathsConverterSpec extends Specification {
],
[someother:
[nested: [
json: "with value",
json : "with value",
anothervalue: 4,
withlist:
withlist :
[
[name: "name2"],
[name: "name1"]
@@ -280,166 +281,166 @@ class JsonToJsonPathsConverterSpec extends Specification {
then:
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" &&
it.jsonPath() == '''$[*].['some'].['nested'][?(@.['json'] == 'with value')]'''
it.jsonPath() == '''$[*].['some'].['nested'][?(@.['json'] == 'with value')]'''
}
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" &&
it.jsonPath() == '''$[*].['some'].['nested'][?(@.['anothervalue'] == 4)]'''
it.jsonPath() == '''$[*].['some'].['nested'][?(@.['anothervalue'] == 4)]'''
}
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" &&
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]'''
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]'''
}
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" &&
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]'''
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]'''
}
pathAndValues.find {
it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").field("['anothernested']").field("['name']").matches("[a-zA-Z]+")""" &&
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*].['anothernested'][?(@.['name'] =~ /[a-zA-Z]+/)]'''
it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*].['anothernested'][?(@.['name'] =~ /[a-zA-Z]+/)]'''
}
when:
json.some.nested.withlist[0][2].anothernested.name = "Kowalski"
then:
assertThatJsonPathsInMapAreValid(JsonOutput.prettyPrint(JsonOutput.toJson(json)), pathAndValues)
}
}
def "should generate assertions for simple response body"() {
given:
String json = """{
String json = """{
"property1": "a",
"property2": "b"
}"""
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method()== """.field("['property2']").isEqualTo("b")""" &&
it.jsonPath() == """\$[?(@.['property2'] == 'b')]"""
}
pathAndValues.find {
it.method() == """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method() == """.field("['property2']").isEqualTo("b")""" &&
it.jsonPath() == """\$[?(@.['property2'] == 'b')]"""
}
and:
pathAndValues.size() == 2
pathAndValues.size() == 2
}
def "should generate assertions for null and boolean values"() {
given:
String json = """{
String json = """{
"property1": "true",
"property2": null,
"property3": false
}"""
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.field("['property1']").isEqualTo("true")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'true')]"""
}
pathAndValues.find {
it.method()== """.field("['property2']").isNull()""" &&
it.jsonPath() == """\$[?(@.['property2'] == null)]"""
}
pathAndValues.find {
it.method()== """.field("['property3']").isEqualTo(false)""" &&
it.jsonPath() == """\$[?(@.['property3'] == false)]"""
}
pathAndValues.find {
it.method() == """.field("['property1']").isEqualTo("true")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'true')]"""
}
pathAndValues.find {
it.method() == """.field("['property2']").isNull()""" &&
it.jsonPath() == """\$[?(@.['property2'] == null)]"""
}
pathAndValues.find {
it.method() == """.field("['property3']").isEqualTo(false)""" &&
it.jsonPath() == """\$[?(@.['property3'] == false)]"""
}
and:
pathAndValues.size() == 3
pathAndValues.size() == 3
}
def "should generate assertions for simple response body constructed from map with a list"() {
given:
Map json = [
property1: 'a',
property2: [
[a: 'sth'],
[b: 'sthElse']
]
]
Map json = [
property1: 'a',
property2: [
[a: 'sth'],
[b: 'sthElse']
]
]
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
then:
pathAndValues.find {
it.method()== """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method()== """.array("['property2']").contains("['a']").isEqualTo("sth")""" &&
it.jsonPath() == """\$.['property2'][*][?(@.['a'] == 'sth')]"""
}
pathAndValues.find {
it.method()== """.array("['property2']").contains("['b']").isEqualTo("sthElse")""" &&
it.jsonPath() == """\$.['property2'][*][?(@.['b'] == 'sthElse')]"""
}
pathAndValues.find {
it.method() == """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method() == """.array("['property2']").contains("['a']").isEqualTo("sth")""" &&
it.jsonPath() == """\$.['property2'][*][?(@.['a'] == 'sth')]"""
}
pathAndValues.find {
it.method() == """.array("['property2']").contains("['b']").isEqualTo("sthElse")""" &&
it.jsonPath() == """\$.['property2'][*][?(@.['b'] == 'sthElse')]"""
}
and:
pathAndValues.size() == 3
pathAndValues.size() == 3
}
@RestoreSystemProperties
def "should generate assertions for simple response body constructed from map with a list with array size check"() {
given:
System.setProperty('spring.cloud.contract.verifier.assert.size', 'true')
Map json = [
property1: 'a',
property2: [
[a: 'sth'],
[b: 'sthElse']
]
]
System.setProperty('spring.cloud.contract.verifier.assert.size', 'true')
Map json = [
property1: 'a',
property2: [
[a: 'sth'],
[b: 'sthElse']
]
]
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
then:
pathAndValues.find {
it.method()== """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method()== """.array("['property2']").contains("['a']").isEqualTo("sth")""" &&
it.jsonPath() == """\$.['property2'][*][?(@.['a'] == 'sth')]"""
}
pathAndValues.find {
it.method()== """.array("['property2']").hasSize(2)""" &&
it.jsonPath() == """\$.['property2'][*]"""
}
pathAndValues.find {
it.method()== """.array("['property2']").contains("['b']").isEqualTo("sthElse")""" &&
it.jsonPath() == """\$.['property2'][*][?(@.['b'] == 'sthElse')]"""
}
pathAndValues.find {
it.method() == """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method() == """.array("['property2']").contains("['a']").isEqualTo("sth")""" &&
it.jsonPath() == """\$.['property2'][*][?(@.['a'] == 'sth')]"""
}
pathAndValues.find {
it.method() == """.array("['property2']").hasSize(2)""" &&
it.jsonPath() == """\$.['property2'][*]"""
}
pathAndValues.find {
it.method() == """.array("['property2']").contains("['b']").isEqualTo("sthElse")""" &&
it.jsonPath() == """\$.['property2'][*][?(@.['b'] == 'sthElse')]"""
}
and:
pathAndValues.size() == 4
pathAndValues.size() == 4
}
def "should generate assertions for a response body containing map with integers as keys"() {
given:
Map json = [
property: [
14: 0.0,
7 : 0.0
]
]
Map json = [
property: [
14: 0.0,
7 : 0.0
]
]
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
then:
pathAndValues.find {
it.method()== """.field("['property']").field(7).isEqualTo(0.0)""" &&
it.jsonPath() == """\$.['property'][?(@.7 == 0.0)]"""
}
pathAndValues.find {
it.method()== """.field("['property']").field(14).isEqualTo(0.0)""" &&
it.jsonPath() == """\$.['property'][?(@.14 == 0.0)]"""
}
pathAndValues.find {
it.method() == """.field("['property']").field(7).isEqualTo(0.0)""" &&
it.jsonPath() == """\$.['property'][?(@.7 == 0.0)]"""
}
pathAndValues.find {
it.method() == """.field("['property']").field(14).isEqualTo(0.0)""" &&
it.jsonPath() == """\$.['property'][?(@.14 == 0.0)]"""
}
and:
pathAndValues.size() == 2
pathAndValues.size() == 2
}
def "should generate assertions for array in response body"() {
given:
String json = """[
String json = """[
{
"property1": "a"
},
@@ -447,25 +448,25 @@ class JsonToJsonPathsConverterSpec extends Specification {
"property2": "b"
}]"""
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.array().contains("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[*][?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method()== """.array().contains("['property2']").isEqualTo("b")""" &&
it.jsonPath() == """\$[*][?(@.['property2'] == 'b')]"""
}
pathAndValues.find {
it.method() == """.array().contains("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[*][?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method() == """.array().contains("['property2']").isEqualTo("b")""" &&
it.jsonPath() == """\$[*][?(@.['property2'] == 'b')]"""
}
and:
pathAndValues.size() == 2
pathAndValues.size() == 2
}
@RestoreSystemProperties
def "should generate assertions for array in response body with array size check"() {
given:
System.setProperty('spring.cloud.contract.verifier.assert.size', 'true')
String json = """[
System.setProperty('spring.cloud.contract.verifier.assert.size', 'true')
String json = """[
{
"property1": "a"
},
@@ -473,100 +474,100 @@ class JsonToJsonPathsConverterSpec extends Specification {
"property2": "b"
}]"""
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.array().contains("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[*][?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method()== """.array().contains("['property2']").isEqualTo("b")""" &&
it.jsonPath() == """\$[*][?(@.['property2'] == 'b')]"""
}
pathAndValues.find {
it.method()== """.hasSize(2)""" &&
it.jsonPath() == """\$"""
}
pathAndValues.find {
it.method() == """.array().contains("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[*][?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method() == """.array().contains("['property2']").isEqualTo("b")""" &&
it.jsonPath() == """\$[*][?(@.['property2'] == 'b')]"""
}
pathAndValues.find {
it.method() == """.hasSize(2)""" &&
it.jsonPath() == """\$"""
}
and:
pathAndValues.size() == 3
pathAndValues.size() == 3
}
def "should generate assertions for array inside response body element"() {
given:
String json = """{
String json = """{
"property1": [
{ "property2": "test1"},
{ "property3": "test2"}
]
}"""
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.array("['property1']").contains("['property2']").isEqualTo("test1")""" &&
it.jsonPath() == """\$.['property1'][*][?(@.['property2'] == 'test1')]"""
}
pathAndValues.find {
it.method()== """.array("['property1']").contains("['property3']").isEqualTo("test2")""" &&
it.jsonPath() == """\$.['property1'][*][?(@.['property3'] == 'test2')]"""
}
pathAndValues.find {
it.method() == """.array("['property1']").contains("['property2']").isEqualTo("test1")""" &&
it.jsonPath() == """\$.['property1'][*][?(@.['property2'] == 'test1')]"""
}
pathAndValues.find {
it.method() == """.array("['property1']").contains("['property3']").isEqualTo("test2")""" &&
it.jsonPath() == """\$.['property1'][*][?(@.['property3'] == 'test2')]"""
}
and:
pathAndValues.size() == 2
pathAndValues.size() == 2
}
@RestoreSystemProperties
def "should generate assertions for array inside response body element with array size check"() {
given:
System.setProperty('spring.cloud.contract.verifier.assert.size', 'true')
String json = """{
System.setProperty('spring.cloud.contract.verifier.assert.size', 'true')
String json = """{
"property1": [
{ "property2": "test1"},
{ "property3": "test2"}
]
}"""
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.array("['property1']").contains("['property2']").isEqualTo("test1")""" &&
it.jsonPath() == """\$.['property1'][*][?(@.['property2'] == 'test1')]"""
}
pathAndValues.find {
it.method()== """.array("['property1']").contains("['property3']").isEqualTo("test2")""" &&
it.jsonPath() == """\$.['property1'][*][?(@.['property3'] == 'test2')]"""
}
pathAndValues.find {
it.method()== """.array("['property1']").hasSize(2)""" &&
it.jsonPath() == """\$.['property1'][*]"""
}
pathAndValues.find {
it.method() == """.array("['property1']").contains("['property2']").isEqualTo("test1")""" &&
it.jsonPath() == """\$.['property1'][*][?(@.['property2'] == 'test1')]"""
}
pathAndValues.find {
it.method() == """.array("['property1']").contains("['property3']").isEqualTo("test2")""" &&
it.jsonPath() == """\$.['property1'][*][?(@.['property3'] == 'test2')]"""
}
pathAndValues.find {
it.method() == """.array("['property1']").hasSize(2)""" &&
it.jsonPath() == """\$.['property1'][*]"""
}
and:
pathAndValues.size() == 3
pathAndValues.size() == 3
}
def "should generate assertions for nested objects in response body"() {
given:
String json = """{
String json = """{
"property1": "a",
"property2": {"property3": "b"}
}"""
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.field("['property2']").field("['property3']").isEqualTo("b")""" &&
it.jsonPath() == """\$.['property2'][?(@.['property3'] == 'b')]"""
}
pathAndValues.find {
it.method()== """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
pathAndValues.find {
it.method() == """.field("['property2']").field("['property3']").isEqualTo("b")""" &&
it.jsonPath() == """\$.['property2'][?(@.['property3'] == 'b')]"""
}
pathAndValues.find {
it.method() == """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
and:
pathAndValues.size() == 2
pathAndValues.size() == 2
}
def "should generate regex assertions for map objects in response body"() {
given:
Map json = [
Map json = [
property1: "a",
property2: Pattern.compile('[0-9]{3}')
]
@@ -574,12 +575,12 @@ class JsonToJsonPathsConverterSpec extends Specification {
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
then:
pathAndValues.find {
it.method()== """.field("['property2']").matches("[0-9]{3}")""" &&
it.jsonPath() == """\$[?(@.['property2'] =~ /[0-9]{3}/)]"""
it.method() == """.field("['property2']").matches("[0-9]{3}")""" &&
it.jsonPath() == """\$[?(@.['property2'] =~ /[0-9]{3}/)]"""
}
pathAndValues.find {
it.method()== """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
it.method() == """.field("['property1']").isEqualTo("a")""" &&
it.jsonPath() == """\$[?(@.['property1'] == 'a')]"""
}
and:
pathAndValues.size() == 2
@@ -587,15 +588,15 @@ class JsonToJsonPathsConverterSpec extends Specification {
def "should generate escaped regex assertions for string objects in response body"() {
given:
Map json = [
Map json = [
property2: Pattern.compile('\\d+')
]
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
then:
pathAndValues.find {
it.method()== """.field("['property2']").matches("\\\\d+")""" &&
it.jsonPath() == """\$[?(@.['property2'] =~ /\\d+/)]"""
it.method() == """.field("['property2']").matches("\\\\d+")""" &&
it.jsonPath() == """\$[?(@.['property2'] =~ /\\d+/)]"""
}
and:
pathAndValues.size() == 1
@@ -603,59 +604,59 @@ class JsonToJsonPathsConverterSpec extends Specification {
def "should work with more complex stuff and jsonpaths"() {
given:
Map json = [
errors: [
[property: "bank_account_number",
message: "incorrect_format"]
]
]
Map json = [
errors: [
[property: "bank_account_number",
message : "incorrect_format"]
]
]
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
then:
pathAndValues.find {
it.method()== """.array("['errors']").contains("['property']").isEqualTo("bank_account_number")""" &&
it.jsonPath() == """\$.['errors'][*][?(@.['property'] == 'bank_account_number')]"""
}
pathAndValues.find {
it.method()== """.array("['errors']").contains("['message']").isEqualTo("incorrect_format")""" &&
it.jsonPath() == """\$.['errors'][*][?(@.['message'] == 'incorrect_format')]"""
}
pathAndValues.find {
it.method() == """.array("['errors']").contains("['property']").isEqualTo("bank_account_number")""" &&
it.jsonPath() == """\$.['errors'][*][?(@.['property'] == 'bank_account_number')]"""
}
pathAndValues.find {
it.method() == """.array("['errors']").contains("['message']").isEqualTo("incorrect_format")""" &&
it.jsonPath() == """\$.['errors'][*][?(@.['message'] == 'incorrect_format')]"""
}
and:
pathAndValues.size() == 2
pathAndValues.size() == 2
}
@RestoreSystemProperties
def "should work with more complex stuff and jsonpaths with array size check"() {
given:
System.setProperty('spring.cloud.contract.verifier.assert.size', 'true')
Map json = [
errors: [
[property: "bank_account_number",
message: "incorrect_format"]
]
]
System.setProperty('spring.cloud.contract.verifier.assert.size', 'true')
Map json = [
errors: [
[property: "bank_account_number",
message : "incorrect_format"]
]
]
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
then:
pathAndValues.find {
it.method()== """.array("['errors']").contains("['property']").isEqualTo("bank_account_number")""" &&
it.jsonPath() == """\$.['errors'][*][?(@.['property'] == 'bank_account_number')]"""
}
pathAndValues.find {
it.method()== """.array("['errors']").contains("['message']").isEqualTo("incorrect_format")""" &&
it.jsonPath() == """\$.['errors'][*][?(@.['message'] == 'incorrect_format')]"""
}
pathAndValues.find {
it.method()== """.array("['errors']").hasSize(1)""" &&
it.jsonPath() == """\$.['errors'][*]"""
}
pathAndValues.find {
it.method() == """.array("['errors']").contains("['property']").isEqualTo("bank_account_number")""" &&
it.jsonPath() == """\$.['errors'][*][?(@.['property'] == 'bank_account_number')]"""
}
pathAndValues.find {
it.method() == """.array("['errors']").contains("['message']").isEqualTo("incorrect_format")""" &&
it.jsonPath() == """\$.['errors'][*][?(@.['message'] == 'incorrect_format')]"""
}
pathAndValues.find {
it.method() == """.array("['errors']").hasSize(1)""" &&
it.jsonPath() == """\$.['errors'][*]"""
}
and:
pathAndValues.size() == 3
pathAndValues.size() == 3
}
def "should manage to parse a double array"() {
given:
String json = '''
String json = '''
[{
"place":
{
@@ -671,29 +672,29 @@ class JsonToJsonPathsConverterSpec extends Specification {
}]
'''
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
DocumentContext context = JsonPath.parse(json)
pathAndValues.each {
assert context.read(it.jsonPath(), JSONArray)
}
DocumentContext context = JsonPath.parse(json)
pathAndValues.each {
assert context.read(it.jsonPath(), JSONArray)
}
and:
pathAndValues.find {
it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().array().arrayField().isEqualTo(38.995548)""" &&
it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.995548)]"""
}
pathAndValues.find {
it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().array().arrayField().isEqualTo(-77.119759)""" &&
it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -77.119759)]"""
}
pathAndValues.find {
it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().array().arrayField().isEqualTo(-76.909393)""" &&
it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -76.909393)]"""
}
pathAndValues.find {
it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().array().arrayField().isEqualTo(38.791645)""" &&
it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.791645)]"""
}
pathAndValues.find {
it.method() == """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().array().arrayField().isEqualTo(38.995548)""" &&
it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.995548)]"""
}
pathAndValues.find {
it.method() == """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().array().arrayField().isEqualTo(-77.119759)""" &&
it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -77.119759)]"""
}
pathAndValues.find {
it.method() == """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().array().arrayField().isEqualTo(-76.909393)""" &&
it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -76.909393)]"""
}
pathAndValues.find {
it.method() == """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().array().arrayField().isEqualTo(38.791645)""" &&
it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.791645)]"""
}
and:
pathAndValues.size() == 4
and:
@@ -788,7 +789,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
given:
String jsonPath = '$.a.b.c.d'
and:
def body = [ a: [ b: [ c: [ d: 1234 ] ] ] ]
def body = [a: [b: [c: [d: 1234]]]]
expect:
'$.a.b.c[?(@.d == 1234)]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.EQUALITY, jsonPath, null), body)
}
@@ -797,7 +798,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
given:
String jsonPath = '$.a.b.c.[\'d.e\']'
and:
def body = [ a: [ b: [ c: [ "d.e" : 1234 ] ] ] ]
def body = [a: [b: [c: ["d.e": 1234]]]]
expect:
'$.a.b.c[?(@.[\'d.e\'] == 1234)]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.EQUALITY, jsonPath, null), body)
}
@@ -806,7 +807,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
given:
String jsonPath = '$.a.b.c.d'
and:
def body = [ a: [ b: [ c: [ d: "foo" ] ] ] ]
def body = [a: [b: [c: [d: "foo"]]]]
expect:
'$.a.b.c[?(@.d == \'foo\')]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.EQUALITY, jsonPath, null), body)
}
@@ -834,7 +835,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
given:
String jsonPath = '$.a.b.c.d'
and:
def body = [ foo: "bar" ]
def body = [foo: "bar"]
when:
JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.EQUALITY, jsonPath, null), body)
then:
@@ -845,8 +846,8 @@ class JsonToJsonPathsConverterSpec extends Specification {
def "should generate assertion for empty map"() {
given:
Map json = [
aMap: ["foo": "bar"],
anEmptyMap: [:]
aMap : ["foo": "bar"],
anEmptyMap: [:]
]
when:
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json)
@@ -856,7 +857,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
it.jsonPath() == """\$.['aMap'][?(@.['foo'] == 'bar')]"""
}
pathAndValues.find {
it.method()== """.field("['anEmptyMap']").isEmpty()""" &&
it.method() == """.field("['anEmptyMap']").isEmpty()""" &&
it.jsonPath() == """\$.['anEmptyMap']"""
}
and:
@@ -865,7 +866,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
def "should generate assertion for empty object"() {
given:
String json = """{
String json = """{
"aMap": {"foo": "bar"},
"anEmptyMap": {}
}"""
@@ -873,7 +874,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.field("['aMap']").field("['foo']").isEqualTo("bar")""" &&
it.method() == """.field("['aMap']").field("['foo']").isEqualTo("bar")""" &&
it.jsonPath() == """\$.['aMap'][?(@.['foo'] == 'bar')]"""
}
pathAndValues.find {

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.util
import org.junit.Rule
@@ -5,12 +21,14 @@ import org.junit.rules.TemporaryFolder
import spock.lang.Specification
import org.springframework.util.FileSystemUtils
/**
* @author Marcin Grzejszczak
*/
class NamesUtilSpec extends Specification {
@Rule TemporaryFolder folder = new TemporaryFolder()
@Rule
TemporaryFolder folder = new TemporaryFolder()
def "should return the whole string before the last one"() {
given:

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.util
import java.lang.reflect.Method
@@ -81,7 +97,7 @@ class SyntaxChecker {
"${ContractVerifierMessagingUtil.name}.headers",
"${JsonAssertion.name}.assertThatJson",
"${SpringCloudContractAssertions.name}.assertThat",
].collect { "import static ${it};"}.join("\n")
].collect { "import static ${it};" }.join("\n")
private static final String WEB_TEST_CLIENT_STATIC_IMPORTS = [
"${RestAssuredWebTestClient.name}.*",
@@ -100,7 +116,8 @@ private void test(String test) {
static void tryToCompile(String builderName, String test) {
if (builderName.toLowerCase().contains("spock")) {
tryToCompileGroovy(builderName, test)
} else {
}
else {
tryToCompileJava(builderName, test)
}
}
@@ -109,7 +126,8 @@ private void test(String test) {
if (builderName.toLowerCase().contains("spock")) {
Script script = tryToCompileGroovy(builderName, test)
script.run()
} else {
}
else {
Class clazz = tryToCompileJava(builderName, test)
Method method = ReflectionUtils.findMethod(clazz, "method")
method.invoke(clazz.newInstance())
@@ -120,7 +138,8 @@ private void test(String test) {
static void tryToCompileWithoutCompileStatic(String builderName, String test) {
if (builderName.toLowerCase().contains("spock")) {
tryToCompileGroovy(builderName, test, false)
} else {
}
else {
tryToCompileJava(builderName, test)
}
}
@@ -184,4 +203,4 @@ private void test(String test) {
return true
}
}
}

View File

@@ -1,17 +1,35 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.util
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import org.springframework.cloud.contract.verifier.converter.YamlContractConverter
import spock.lang.Specification
import org.springframework.cloud.contract.verifier.converter.YamlContractConverter
/**
* @author Marcin Grzejszczak
* @since
*/
class ToFileContractsTransformerSpec extends Specification {
@Rule TemporaryFolder tmp = new TemporaryFolder()
@Rule
TemporaryFolder tmp = new TemporaryFolder()
File folder
def setup() {

View File

@@ -24,17 +24,17 @@ import spock.lang.Unroll
*/
class XPathSpec extends Specification {
@Unroll
def "should generate [#expectedXPath] for XPath [#xPath]"() {
expect:
xPath == expectedXPath
where:
xPath || expectedXPath
XPathBuilder.builder().node("some").node("nested").node("anothervalue").isEqualTo(4).xPath() || '''/some/nested[anothervalue=4]'''
XPathBuilder.builder().node("some").node("nested").array("withlist").contains("name").isEqualTo("name1").xPath() || '''/some/nested/withlist[name='name1']'''
XPathBuilder.builder().node("some").node("nested").array("withlist").contains("name").isEqualTo("name2").xPath() || '''/some/nested/withlist[name='name2']'''
XPathBuilder.builder().node("some").node("nested").node("json").isEqualTo("with \"val'ue").xPath() || '''/some/nested[json=concat('with "val',"'",'ue')]'''
XPathBuilder.builder().node("some", "nested", "json").isEqualTo("with \"val'ue").xPath() || '''/some/nested[json=concat('with "val',"'",'ue')]'''
}
@Unroll
def "should generate [#expectedXPath] for XPath [#xPath]"() {
expect:
xPath == expectedXPath
where:
xPath || expectedXPath
XPathBuilder.builder().node("some").node("nested").node("anothervalue").isEqualTo(4).xPath() || '''/some/nested[anothervalue=4]'''
XPathBuilder.builder().node("some").node("nested").array("withlist").contains("name").isEqualTo("name1").xPath() || '''/some/nested/withlist[name='name1']'''
XPathBuilder.builder().node("some").node("nested").array("withlist").contains("name").isEqualTo("name2").xPath() || '''/some/nested/withlist[name='name2']'''
XPathBuilder.builder().node("some").node("nested").node("json").isEqualTo("with \"val'ue").xPath() || '''/some/nested[json=concat('with "val',"'",'ue')]'''
XPathBuilder.builder().node("some", "nested", "json").isEqualTo("with \"val'ue").xPath() || '''/some/nested[json=concat('with "val',"'",'ue')]'''
}
}

View File

@@ -591,4 +591,4 @@ class XmlAssertionSpec extends Specification {
e.message.contains("has size [0] and not [1] for XPath <count(/root/foo)>")
}
}
}

View File

@@ -1,4 +1,4 @@
# tag::extension[]
org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockExtensions=\
org.springframework.cloud.contract.verifier.dsl.wiremock.TestWireMockExtensions
# end::extension[]
# end::extension[]

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {

View File

@@ -1,3 +1,3 @@
{
"status": "REQUEST"
}
}

View File

@@ -1,3 +1,3 @@
{
"status": "RESPONSE"
}
}

View File

@@ -1,21 +1,21 @@
import org.springframework.cloud.contract.spec.Contract
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
request {
method('PUT')

View File

@@ -42,4 +42,4 @@ response:
- key: foo2
regex: bar
- key: foo3
command: andMeToo($it)
command: andMeToo($it)

View File

@@ -1,27 +1,46 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description("""Should send a message in topic coupon_collected""")
description("""Should send a message in topic coupon_collected""")
label 'couponCollectedV1'
label 'couponCollectedV1'
input {
triggeredBy('couponCollectedSm()')
}
input {
triggeredBy('couponCollectedSm()')
}
outputMessage {
sentTo('coupon_collected')
outputMessage {
sentTo('coupon_collected')
body([
receiverSnId: value(consumer("receiver-sn-id"), producer(regex('([^\\W]|-)+'))),
sessionId: value(consumer(7928568413097907541), producer(regex('\\d+'))),
createdTs: value(consumer(1504688949158), producer(regex('\\d+'))),
couponToken: value(consumer("440006-6-1504688949139-xyuzzrx5"), producer(regex('([^\\W]|-)+')))
])
body([
receiverSnId:
value(consumer("receiver-sn-id"), producer(regex('([^\\W]|-)+'))),
sessionId : value(consumer(7928568413097907541), producer(regex('\\d+'))),
createdTs : value(consumer(1504688949158), producer(regex('\\d+'))),
couponToken : value(
consumer("440006-6-1504688949139-xyuzzrx5"),
producer(regex('([^\\W]|-)+')))
])
headers {
messagingContentType(applicationJsonUtf8())
}
}
}
headers {
messagingContentType(applicationJsonUtf8())
}
}
}

View File

@@ -1,27 +1,46 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description("""Should send a message in topic coupon_collected""")
description("""Should send a message in topic coupon_collected""")
label 'couponCollectedSm'
label 'couponCollectedSm'
input {
triggeredBy('couponCollectedSm()')
}
input {
triggeredBy('couponCollectedSm()')
}
outputMessage {
sentTo('coupon_collected')
outputMessage {
sentTo('coupon_collected')
body([
receiverSnId: value(consumer("receiver-sn-id"), producer(regex('([^\\W]|-)+'))),
sessionId: value(consumer(7928568413097907541), producer(regex('\\d+'))),
createdTs: value(consumer(1504688949158), producer(regex('\\d+'))),
couponToken: value(consumer("440006-6-1504688949139-xyuzzrx5"), producer(regex('([^\\W]|-)+')))
])
body([
receiverSnId:
value(consumer("receiver-sn-id"), producer(regex('([^\\W]|-)+'))),
sessionId : value(consumer(7928568413097907541), producer(regex('\\d+'))),
createdTs : value(consumer(1504688949158), producer(regex('\\d+'))),
couponToken : value(
consumer("440006-6-1504688949139-xyuzzrx5"),
producer(regex('([^\\W]|-)+')))
])
headers {
messagingContentType(applicationJsonUtf8())
}
}
}
headers {
messagingContentType(applicationJsonUtf8())
}
}
}

View File

@@ -1,27 +1,45 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description("""Should send a message in topic coupon_sent""")
description("""Should send a message in topic coupon_sent""")
label 'couponSentSm'
label 'couponSentSm'
input {
triggeredBy('couponSentSm()')
}
input {
triggeredBy('couponSentSm()')
}
outputMessage {
sentTo('coupon_sent')
outputMessage {
sentTo('coupon_sent')
body([
senderUserId: value(consumer(123), producer(regex('\\d+'))),
sessionId: value(consumer(7928568413097907541), producer(regex('\\d+'))),
createdTs: value(consumer(1504688949158), producer(regex('\\d+'))),
couponToken: value(consumer("440006-6-1504688949139-xyuzzrx5"), producer(regex('([^\\W]|-)+')))
])
body([
senderUserId: value(consumer(123), producer(regex('\\d+'))),
sessionId : value(consumer(7928568413097907541), producer(regex('\\d+'))),
createdTs : value(consumer(1504688949158), producer(regex('\\d+'))),
couponToken : value(
consumer("440006-6-1504688949139-xyuzzrx5"),
producer(regex('([^\\W]|-)+')))
])
headers {
messagingContentType(applicationJsonUtf8())
}
}
}
headers {
messagingContentType(applicationJsonUtf8())
}
}
}

View File

@@ -1,38 +1,54 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description('Should return bet ranges array')
request {
method 'GET'
url('/admin/v1/spin/betRanges')
}
description('Should return bet ranges array')
request {
method 'GET'
url('/admin/v1/spin/betRanges')
}
response {
status 200
body(
betRanges: [
[
betRangeId : 3,
fromBetPercent: -1
],
[
betRangeId : 4,
fromBetPercent: 0
],
[
betRangeId : 1,
fromBetPercent: 90
],
[
betRangeId : 2,
fromBetPercent: 130
]
]
)
response {
status 200
body(
betRanges: [
[
betRangeId : 3,
fromBetPercent: -1
],
[
betRangeId : 4,
fromBetPercent: 0
],
[
betRangeId : 1,
fromBetPercent: 90
],
[
betRangeId : 2,
fromBetPercent: 130
]
]
)
headers {
contentType(applicationJsonUtf8())
}
}
headers {
contentType(applicationJsonUtf8())
}
}
}

View File

@@ -1,30 +1,46 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description("""
description("""
Should return empty array if user has no friends
""")
request {
method 'GET'
urlPath('/SocialServer/social/getFriends')
url('/social/getFriends') {
queryParameters {
parameter 'snId': $(consumer(regex('([^\\W]|-)+')), producer('12345'))
parameter 'snType': $(consumer(regex('\\d+')), producer(2))
}
}
}
request {
method 'GET'
urlPath('/SocialServer/social/getFriends')
url('/social/getFriends') {
queryParameters {
parameter 'snId': $(consumer(regex('([^\\W]|-)+')), producer('12345'))
parameter 'snType': $(consumer(regex('\\d+')), producer(2))
}
}
}
response {
status 200
body(
"""
response {
status 200
body(
"""
{"friends" : []}
""")
headers {
contentType(applicationJsonUtf8())
}
}
headers {
contentType(applicationJsonUtf8())
}
}
}

View File

@@ -1,44 +1,60 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description("""
description("""
User's information should be update if has appropriate age
""")
request {
method 'POST'
url '/test/updateUserInfo'
body([
userId: 123,
age: 25,
firstName: "asd",
lastName: "asd"
])
stubMatchers {
jsonPath('$.userId', byRegex("[1-9]{1}([0-9]{7})"))
jsonPath('$.age', byRegex("(1[89]|[2-9][0-9])"))
jsonPath('$.firstName', byRegex("[a-zA-Z]{2,20}"))
jsonPath('$.lastName', byRegex("[a-zA-Z]{2,20}"))
}
headers {
contentType(applicationJson())
}
}
response {
status 200
body([
userId: fromRequest().body("userId"),
age: fromRequest().body("age"),
firstName: fromRequest().body("firstName"),
lastName: fromRequest().body("lastName")
])
testMatchers {
jsonPath('$.userId', byEquality())
jsonPath('$.age', byEquality())
jsonPath('$.firstName', byEquality())
jsonPath('$.lastName', byEquality())
}
headers {
contentType(applicationJson())
}
}
}
request {
method 'POST'
url '/test/updateUserInfo'
body([
userId : 123,
age : 25,
firstName: "asd",
lastName : "asd"
])
stubMatchers {
jsonPath('$.userId', byRegex("[1-9]{1}([0-9]{7})"))
jsonPath('$.age', byRegex("(1[89]|[2-9][0-9])"))
jsonPath('$.firstName', byRegex("[a-zA-Z]{2,20}"))
jsonPath('$.lastName', byRegex("[a-zA-Z]{2,20}"))
}
headers {
contentType(applicationJson())
}
}
response {
status 200
body([
userId : fromRequest().body("userId"),
age : fromRequest().body("age"),
firstName: fromRequest().body("firstName"),
lastName : fromRequest().body("lastName")
])
testMatchers {
jsonPath('$.userId', byEquality())
jsonPath('$.age', byEquality())
jsonPath('$.firstName', byEquality())
jsonPath('$.lastName', byEquality())
}
headers {
contentType(applicationJson())
}
}
}

View File

@@ -13,4 +13,4 @@ inbound:
headers:
foo2: bar
body:
foo2: bar
foo2: bar

View File

@@ -10,4 +10,4 @@ response:
headers:
foo2: bar
body:
foo2: bar
foo2: bar

View File

@@ -1,21 +1,21 @@
import org.springframework.cloud.contract.spec.Contract
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
request {
method('PUT')
@@ -37,7 +37,9 @@ Contract.make {
{
"name": "Jan",
"id": "${value(consumer('123'), producer('321'))}",
"surname": "${value(consumer('Kowalsky'), producer('$checkIfSurnameValid($value)'))}"
"surname": "${
value(consumer('Kowalsky'), producer('$checkIfSurnameValid($value)'))
}"
}
"""
)

View File

@@ -20,4 +20,4 @@
"Content-Type": "application/vnd.loanapplicationservice.v1+json"
}
}
}
}

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,21 +1,21 @@
import org.springframework.cloud.contract.spec.Contract
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
Contract.make {
request {
method('PUT')
@@ -37,7 +37,9 @@ Contract.make {
{
"name": "Jan",
"id": "${value(consumer('123'), producer('321'))}",
"surname": "${value(consumer('Kowalsky'), producer('$checkIfSurnameValid($value)'))}"
"surname": "${
value(consumer('Kowalsky'), producer('$checkIfSurnameValid($value)'))
}"
}
"""
)

View File

@@ -0,0 +1,17 @@
//
// Copyright 2013-2019 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

View File

@@ -1,20 +1,21 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.contract.spec.Contract
/*
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(1..2).collect { int index ->
Contract.make {
request {

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,18 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,18 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -1,16 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@@ -20,4 +20,4 @@
"Content-Type": "application/vnd.loanapplicationservice.v1+json"
}
}
}
}

View File

@@ -20,4 +20,4 @@
"Content-Type": "application/vnd.loanapplicationservice.v1+json"
}
}
}
}

View File

@@ -12,31 +12,31 @@ ignored: true
#end::ignored[]
#tag::request[]
request:
#end::request[]
#tag::request_obligatory[]
#end::request[]
#tag::request_obligatory[]
method: PUT
url: /foo
#end::request_obligatory[]
#tag::query_params[]
#end::request_obligatory[]
#tag::query_params[]
queryParameters:
a: b
b: c
#tag::query_params[]
#tag::headers[]
#tag::query_params[]
#tag::headers[]
headers:
foo: bar
fooReq: baz
#end::headers[]
#tag::cookies[]
#end::headers[]
#tag::cookies[]
cookies:
foo: bar
fooReq: baz
#end::cookies[]
#tag::body[]
#end::cookies[]
#tag::body[]
body:
foo: bar
#end::body[]
#tag::request_matcher[]
#end::body[]
#tag::request_matcher[]
matchers:
body:
- path: $.foo
@@ -48,10 +48,10 @@ request:
#end::request_matcher[]
#tag::response[]
response:
#end::response[]
#tag::response_obligatory[]
#end::response[]
#tag::response_obligatory[]
status: 200
#end::response_obligatory[]
#end::response_obligatory[]
fixedDelayMilliseconds: 1000
headers:
foo2: bar
@@ -81,4 +81,4 @@ response:
- key: foo2
regex: bar
- key: foo3
predefined:
predefined:

View File

@@ -43,4 +43,4 @@ response:
- key: source
regex: ip_address
- key: fooPredefinedRegex
predefined: any_boolean
predefined: any_boolean

View File

@@ -9,4 +9,4 @@ response:
matchers:
headers:
- key: foo2
regex: barrrr
regex: barrrr

View File

@@ -4,4 +4,4 @@ request:
bodyFromFile: request.json
response:
status: 200
bodyFromFile: response.json
bodyFromFile: response.json

View File

@@ -144,7 +144,7 @@ response:
valueWithMinEmpty: []
valueWithMaxEmpty: []
key:
'complex.key' : 'foo'
'complex.key': 'foo'
nulValue: null
matchers:
headers:
@@ -203,4 +203,4 @@ response:
type: by_null
value: null
headers:
Content-Type: application/json
Content-Type: application/json

View File

@@ -20,4 +20,4 @@ outputMessage:
bookName: foo
# the headers of the output message
headers:
BOOK-NAME: foo
BOOK-NAME: foo

View File

@@ -72,7 +72,7 @@ outputMessage:
valueWithMinEmpty: []
valueWithMaxEmpty: []
key:
'complex.key' : 'foo'
'complex.key': 'foo'
matchers:
headers:
- key: Content-Type
@@ -122,4 +122,4 @@ outputMessage:
type: by_command
value: assertThatValueIsANumber($it)
headers:
contentType: application/json
contentType: application/json

View File

@@ -14,4 +14,4 @@ outputMessage:
bookName: foo
# the headers of the output message
headers:
BOOK-NAME: foo
BOOK-NAME: foo

View File

@@ -1,11 +1,11 @@
label: some_label
input:
messageFrom: jms:input
messageBodyFromFileAsBytes: request.pdf
messageHeaders:
contentType: application/octet-stream
messageFrom: jms:input
messageBodyFromFileAsBytes: request.pdf
messageHeaders:
contentType: application/octet-stream
outputMessage:
sentTo: jms:output
bodyFromFileAsBytes: response.pdf
headers:
contentType: application/octet-stream
sentTo: jms:output
bodyFromFileAsBytes: response.pdf
headers:
contentType: application/octet-stream

View File

@@ -5,7 +5,7 @@ request:
Content-Type: multipart/form-data;boundary=AaB03x
multipart:
params:
# key (parameter name), value (parameter value) pair
# key (parameter name), value (parameter value) pair
formParameter: '"formParameterValue"'
someBooleanParameter: true
named:
@@ -26,4 +26,4 @@ request:
fileContent:
predefined: non_empty
response:
status: 200
status: 200

View File

@@ -1,11 +1,11 @@
request:
url: /1
method: PUT
headers:
Content-Type: application/octet-stream
bodyFromFileAsBytes: request.pdf
url: /1
method: PUT
headers:
Content-Type: application/octet-stream
bodyFromFileAsBytes: request.pdf
response:
status: 200
bodyFromFileAsBytes: response.pdf
headers:
Content-Type: application/octet-stream
status: 200
bodyFromFileAsBytes: response.pdf
headers:
Content-Type: application/octet-stream

View File

@@ -27,4 +27,4 @@ response:
fullBody: "{{{ request.body }}}"
responseFoo: "{{{ jsonpath this '$.foo' }}}"
responseBaz: "{{{ jsonpath this '$.baz' }}}"
responseBaz2: "Bla bla {{{ jsonpath this '$.foo' }}} bla bla"
responseBaz2: "Bla bla {{{ jsonpath this '$.foo' }}} bla bla"

View File

@@ -46,4 +46,4 @@ response:
- key: foo2
regex: bar
- key: foo3
command: andMeToo($it)
command: andMeToo($it)

View File

@@ -6,7 +6,7 @@ ignored: true
request:
method: PUT
urlPath: /foo
#end::url_path[]
#end::url_path[]
queryParameters:
a: b
b: c
@@ -48,4 +48,4 @@ response:
- key: foo2
regex: bar
- key: foo3
command: andMeToo($it)
command: andMeToo($it)

View File

@@ -23,13 +23,13 @@ request:
</test>
matchers:
body:
- path: /test/duck/text()
type: by_regex
value: "[0-9]{10}"
- path: /test/duck/text()
type: by_equality
- path: /test/time/text()
type: by_time
- path: /test/duck/text()
type: by_regex
value: "[0-9]{10}"
- path: /test/duck/text()
type: by_equality
- path: /test/time/text()
type: by_time
response:
status: 200
headers:
@@ -54,15 +54,15 @@ response:
</test>
matchers:
body:
- path: /test/duck/text()
type: by_regex
value: "[0-9]{10}"
- path: /test/duck/text()
type: by_command
value: "test($it)"
- path: /test/duck/xxx
type: by_null
- path: /test/duck/text()
type: by_equality
- path: /test/time/text()
type: by_time
- path: /test/duck/text()
type: by_regex
value: "[0-9]{10}"
- path: /test/duck/text()
type: by_command
value: "test($it)"
- path: /test/duck/xxx
type: by_null
- path: /test/duck/text()
type: by_equality
- path: /test/time/text()
type: by_time

View File

@@ -16,4 +16,6 @@ request:
method: POST
url: /users/3
response:
status: 200
status: 200

View File

@@ -1 +1,3 @@
{ "hello" : "request" }
{
"hello": "request"
}

View File

@@ -1 +1,3 @@
{ "hello" : "response" }
{
"hello": "response"
}