Merge branch '2.1.x'

This commit is contained in:
Olga Maciaszek-Sharma
2019-04-26 17:06:54 +02:00
2 changed files with 180 additions and 54 deletions

View File

@@ -26,6 +26,7 @@ import groovy.transform.CompileStatic
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.codehaus.groovy.runtime.GStringImpl
import org.xml.sax.helpers.DefaultHandler
import org.springframework.cloud.contract.spec.internal.DslProperty
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
@@ -35,7 +36,7 @@ import org.springframework.cloud.contract.spec.internal.Headers
import org.springframework.cloud.contract.spec.internal.MatchingStrategy
import org.springframework.cloud.contract.spec.internal.NamedProperty
import org.springframework.cloud.contract.spec.internal.OptionalProperty
import org.xml.sax.helpers.DefaultHandler
import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor
import static org.apache.commons.text.StringEscapeUtils.escapeJava
import static org.apache.commons.text.StringEscapeUtils.escapeJson
@@ -128,7 +129,8 @@ class ContentUtils {
catch (JsonException e) {
try {
getXmlSlurperWithDefaultErrorHandler()
.parseText(extractValueForXML(bodyAsValue, GET_STUB_SIDE).toString())
.parseText(
extractValueForXML(bodyAsValue, GET_STUB_SIDE).toString())
return ContentType.XML
}
catch (Exception ignored) {
@@ -145,7 +147,7 @@ class ContentUtils {
}
catch (JsonException e) {
try {
getXmlSlurperWithDefaultErrorHandler()
getXmlSlurperWithDefaultErrorHandler()
.parseText(bodyAsValue)
return ContentType.XML
}
@@ -244,7 +246,9 @@ class ContentUtils {
private static Object extractValueForJSON(GString bodyAsValue, Closure valueProvider) {
GString transformedString = new GStringImpl(
bodyAsValue.values.
collect { transformJSONStringValue(it, valueProvider) } as String[],
collect {
transformJSONStringValue(it, valueProvider)
} as String[],
bodyAsValue.strings.clone() as String[]
)
def parsedJson = new JsonSlurper().
@@ -255,7 +259,9 @@ class ContentUtils {
private static GStringImpl extractValueForXML(GString bodyAsValue, Closure valueProvider) {
GStringImpl impl = new GStringImpl(
bodyAsValue.values.
collect { transformXMLStringValue(it, valueProvider) } as String[],
collect {
transformXMLStringValue(it, valueProvider)
} as String[],
bodyAsValue.strings.clone() as String[]
)
// try to convert it to XML
@@ -396,26 +402,28 @@ class ContentUtils {
if (content?.contains("octet-stream")) {
return UNKNOWN
}
if (content) {
if (content && isNotTemplate(content)) {
return DEFINED
}
return UNKNOWN
}
static ContentType recognizeContentTypeFromHeader(Headers headers) {
return recognizeContentTypeFromHeader(headers, { Header header -> header?.clientValue })
return recognizeContentTypeFromHeader(headers,
{ Header header -> header?.clientValue })
}
static ContentType recognizeContentTypeFromTestHeader(Headers headers) {
return recognizeContentTypeFromHeader(headers, { Header header -> header?.serverValue })
return recognizeContentTypeFromHeader(headers,
{ Header header -> header?.serverValue })
}
static MatchingStrategy.Type getEqualsTypeFromContentType(ContentType contentType) {
switch (contentType) {
case JSON:
return MatchingStrategy.Type.EQUAL_TO_JSON
case ContentType.XML:
return MatchingStrategy.Type.EQUAL_TO_XML
case JSON:
return MatchingStrategy.Type.EQUAL_TO_JSON
case ContentType.XML:
return MatchingStrategy.Type.EQUAL_TO_XML
}
return MatchingStrategy.Type.EQUAL_TO
}
@@ -523,10 +531,10 @@ class ContentUtils {
static ContentType recognizeContentTypeFromMatchingStrategy(MatchingStrategy.Type type) {
switch (type) {
case MatchingStrategy.Type.EQUAL_TO_XML:
return ContentType.XML
case MatchingStrategy.Type.EQUAL_TO_JSON:
return JSON
case MatchingStrategy.Type.EQUAL_TO_XML:
return ContentType.XML
case MatchingStrategy.Type.EQUAL_TO_JSON:
return JSON
}
return UNKNOWN
}
@@ -579,7 +587,8 @@ class ContentUtils {
if (fromFileProperty.isByte()) {
return bytesFromFile(fromFileProperty)
}
return "[" + fromFileProperty.asBytes().collect { it }.join(", ") + "] as byte[]"
return "[" + fromFileProperty.asBytes().collect { it }.
join(", ") + "] as byte[]"
}
return quote +
escapeJava(property.value.serverValue.toString()) + quote + ".bytes"
@@ -598,9 +607,11 @@ class ContentUtils {
if (fromFileProperty.isByte()) {
return bytesFromFile(fromFileProperty)
}
return "new byte[] {" + fromFileProperty.asBytes().collect { it }.join(", ") + "}"
return "new byte[] {" + fromFileProperty.asBytes().collect { it }.
join(", ") + "}"
}
return quote + escapeJava(property.value.serverValue.toString()) + quote + ".getBytes()"
return quote +
escapeJava(property.value.serverValue.toString()) + quote + ".getBytes()"
}
static ContentType evaluateContentType(Headers contractHeaders, Object body) {
@@ -620,6 +631,11 @@ class ContentUtils {
XmlSlurper xmlSlurper = new XmlSlurper()
xmlSlurper.setErrorHandler(new DefaultHandler())
return xmlSlurper
}
}
private static boolean isNotTemplate(String content) {
return !new HandlebarsTemplateProcessor().containsTemplateEntry(content)
}
}

View File

@@ -1,5 +1,5 @@
/*
* 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.
@@ -67,22 +67,26 @@ class MethodBodyBuilderSpec extends Specification implements WireMockStubVerifie
body([
myArray: [
[
notABugGeneratedHere : $(c('foo'), p(execute('assertThat((String)$it).isEqualTo("foo")'))),
notABugGeneratedHere : $(c('foo'),
p(execute('assertThat((String)$it).isEqualTo("foo")'))),
anotherArrayNeededForBug : [
[
optionalNotEmpty: $(c('foo'), p(execute('assertThat((String)$it).isEqualTo("12")')))
optionalNotEmpty: $(c('foo'),
p(execute('assertThat((String)$it).isEqualTo("12")')))
]
],
yetAnotherArrayNeededForBug: [
[
optionalNotEmpty: $(c('foo'), p(execute('assertThat((String)$it).isEqualTo("22")')))
optionalNotEmpty: $(c('foo'),
p(execute('assertThat((String)$it).isEqualTo("22")')))
]
]
],
[
anotherArrayNeededForBug2: [
[
optionalNotEmpty: $(c('foo'), p(execute('assertThat((String)$it).isEqualTo("122")')))
optionalNotEmpty: $(c('foo'),
p(execute('assertThat((String)$it).isEqualTo("122")')))
]
]
],
@@ -213,7 +217,8 @@ DocumentContext parsedJson = JsonPath.parse(json);
response {
status OK()
body(
foo: ["my.dotted.response": $(c('foo'), p(execute('"foo".equals($it)')))]
foo: ["my.dotted.response":
$(c('foo'), p(execute('"foo".equals($it)')))]
)
headers {
contentType(applicationJson())
@@ -308,7 +313,8 @@ DocumentContext parsedJson = JsonPath.parse(json);
assert e.message.contains("Parsed JSON [{}] doesn't match the JSON path")
}
catch (InvocationTargetException e1) {
assert e1.cause.message.contains("Parsed JSON [{}] doesn't match the JSON path")
assert e1.cause.message.
contains("Parsed JSON [{}] doesn't match the JSON path")
}
where:
methodBuilderName | methodBuilder
@@ -388,11 +394,30 @@ DocumentContext parsedJson = JsonPath.parse(json);
asserter(test)
where:
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.*')") }
JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> testBody.contains('assertThat(response.getHeaderString("Content-Length")).isEqualTo(4);') && testBody.contains('assertThat(response.getHeaderString("Content-Type")).matches("application/pdf.*");') }
WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> testBody.contains('assertThat(response.header("Content-Length")).isEqualTo(4);') && testBody.contains('assertThat(response.header("Content-Type")).matches("application/pdf.*");') }
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.*')")
}
JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody ->
testBody.
contains('assertThat(response.getHeaderString("Content-Length")).isEqualTo(4);') && testBody.
contains('assertThat(response.getHeaderString("Content-Type")).matches("application/pdf.*");')
}
WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody ->
testBody.
contains('assertThat(response.header("Content-Length")).isEqualTo(4);') && testBody.
contains('assertThat(response.header("Content-Type")).matches("application/pdf.*");')
}
}
def 'should put L on long values [#methodBuilderName]'() {
@@ -415,10 +440,14 @@ DocumentContext parsedJson = JsonPath.parse(json);
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['createdAt']").isEqualTo(1502766000000L)""")
blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['updatedAt']").isEqualTo(1499476115000L)""")
blockBuilder.toString().
contains("""assertThatJson(parsedJson).field("['createdAt']").isEqualTo(1502766000000L)""")
blockBuilder.toString().
contains("""assertThatJson(parsedJson).field("['updatedAt']").isEqualTo(1499476115000L)""")
and:
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString())
SyntaxChecker.
tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.
toString())
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
@@ -452,7 +481,9 @@ DocumentContext parsedJson = JsonPath.parse(json);
then:
!blockBuilder.toString().contains('myheader')
and:
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString())
SyntaxChecker.
tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.
toString())
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
@@ -490,11 +521,21 @@ DocumentContext parsedJson = JsonPath.parse(json);
stubMappingIsValidWireMockStub(contractDsl)
where:
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"') }
JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> string.contains('assertThat(responseBody).isEqualTo("My name");') }
WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> string.contains('assertThat(responseBody).isEqualTo("My name");') }
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"')
}
JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string ->
string.contains('assertThat(responseBody).isEqualTo("My name");')
}
WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string ->
string.contains('assertThat(responseBody).isEqualTo("My name");')
}
}
@Issue('#559')
@@ -551,9 +592,12 @@ DocumentContext parsedJson = JsonPath.parse(json);
}
body(
[
"name" : $(consumer(~/.+/), producer('string-1')),
"updatedTs" : $(consumer(regex(~/1531916906000/).asLong())),
"isDisabled": $(consumer(regex(anyBoolean())), producer(true))
"name" :
$(consumer(~/.+/), producer('string-1')),
"updatedTs" :
$(consumer(regex(~/1531916906000/).asLong())),
"isDisabled": $(consumer(regex(anyBoolean())),
producer(true))
]
)
}
@@ -903,9 +947,12 @@ DocumentContext parsedJson = JsonPath.parse(json);
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['nullValue']").isNull()""")
blockBuilder.toString().
contains("""assertThatJson(parsedJson).field("['nullValue']").isNull()""")
and:
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString())
SyntaxChecker.
tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.
toString())
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
@@ -1298,8 +1345,10 @@ DocumentContext parsedJson = JsonPath.parse(json);
status OK()
body($(consumer("some-content"), producer(regex(nonBlank()))))
headers {
header(contentLength(), $(consumer(2647691), producer(regex(positiveInt()))))
header(contentType(), $(consumer(applicationOctetStream()), producer(regex(nonBlank()))))
header(contentLength(),
$(consumer(2647691), producer(regex(positiveInt()))))
header(contentType(), $(consumer(applicationOctetStream()),
producer(regex(nonBlank()))))
}
}
}
@@ -1314,11 +1363,27 @@ DocumentContext parsedJson = JsonPath.parse(json);
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | asserter
"MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent -> assert testContent.contains('''response.header('Content-Length') ==~ java.util.regex.Pattern.compile('([1-9]\\\\d*)')''') && testContent.contains('''response.header('Content-Type') ==~ java.util.regex.Pattern.compile('^\\\\s*\\\\S[\\\\S\\\\s]*')'''); return true }
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent -> assert testContent.contains('''assertThat(response.header("Content-Type")).matches("^\\\\s*\\\\S[\\\\S\\\\s]*")''') && testContent.contains('''assertThat(response.header("Content-Length")).matches("([1-9]\\\\d*)")'''); return true }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent -> assert testContent.contains('''response.getHeaderString('Content-Length') ==~ java.util.regex.Pattern.compile('([1-9]\\\\d*)')''') && testContent.contains('''response.getHeaderString('Content-Type') ==~ java.util.regex.Pattern.compile('^\\\\s*\\\\S[\\\\S\\\\s]*')'''); return true }
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent -> assert testContent.contains('''assertThat(response.getHeaderString("Content-Type")).matches("^\\\\s*\\\\S[\\\\S\\\\s]*")''') && testContent.contains('''assertThat(response.getHeaderString("Content-Length")).matches("([1-9]\\\\d*)")'''); return true }
methodBuilderName | methodBuilder | asserter
"MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent ->
assert testContent.
contains('''response.header('Content-Length') ==~ java.util.regex.Pattern.compile('([1-9]\\\\d*)')''') && testContent.
contains('''response.header('Content-Type') ==~ java.util.regex.Pattern.compile('^\\\\s*\\\\S[\\\\S\\\\s]*')'''); return true
}
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent ->
assert testContent.
contains('''assertThat(response.header("Content-Type")).matches("^\\\\s*\\\\S[\\\\S\\\\s]*")''') && testContent.
contains('''assertThat(response.header("Content-Length")).matches("([1-9]\\\\d*)")'''); return true
}
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent ->
assert testContent.
contains('''response.getHeaderString('Content-Length') ==~ java.util.regex.Pattern.compile('([1-9]\\\\d*)')''') && testContent.
contains('''response.getHeaderString('Content-Type') ==~ java.util.regex.Pattern.compile('^\\\\s*\\\\S[\\\\S\\\\s]*')'''); return true
}
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent ->
assert testContent.
contains('''assertThat(response.getHeaderString("Content-Type")).matches("^\\\\s*\\\\S[\\\\S\\\\s]*")''') && testContent.
contains('''assertThat(response.getHeaderString("Content-Length")).matches("([1-9]\\\\d*)")'''); return true
}
}
@Issue("#1034")
@@ -1387,7 +1452,8 @@ response:
File tmpFile = File.createTempFile("foo", ".yml")
tmpFile.createNewFile()
tmpFile.text = yaml
Contract contractDsl = new YamlContractConverter().convertFrom(tmpFile).first()
Contract contractDsl = new YamlContractConverter().convertFrom(tmpFile).
first()
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
@@ -1440,4 +1506,48 @@ response:
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) }
}
def 'should resolve headers from request correctly'() {
given:
Contract contractDsl = Contract.make {
request {
method PUT()
url '/frauds/name'
body([
name: $(anyAlphaUnicode())
])
headers {
contentType("application/json")
}
}
response {
status OK()
body([
result: "Don't worry ${fromRequest().body('$.name')} you're not a fraud"
])
headers {
header(contentType(), "${fromRequest().header(contentType())};charset=UTF-8")
}
}
}
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
String test = blockBuilder.toString()
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test)
and:
test.contains($/assertThatJson(parsedJson).field("['result']").isEqualTo("Don't worry/$)
test.contains("you're not a fraud")
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) }
}
}