allow sendMessage to handle body from file (#1867)
* allow sendMessage to handle body from file - add test for populating `bodyFromFileAsBytes` - update `StubRunnerExecutor` to handle more than just json payloads cherry picked changes from bugfix/1864 take 2 fixes #1864 * wrap bodyextractor value in jsonoutput, add tests for of file content types cherry picked from bugfix/1864 #1864
This commit is contained in:
@@ -35,13 +35,14 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.cloud.contract.spec.Contract;
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.Headers;
|
||||
import org.springframework.cloud.contract.spec.internal.OutputMessage;
|
||||
import org.springframework.cloud.contract.stubrunner.AvailablePortScanner.PortCallback;
|
||||
import org.springframework.cloud.contract.stubrunner.provider.wiremock.WireMockHttpServerStub;
|
||||
import org.springframework.cloud.contract.verifier.converter.YamlContract;
|
||||
import org.springframework.cloud.contract.verifier.converter.YamlContractConverter;
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifierSender;
|
||||
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessageMetadata;
|
||||
import org.springframework.cloud.contract.verifier.messaging.noop.NoOpStubMessages;
|
||||
import org.springframework.cloud.contract.verifier.util.BodyExtractor;
|
||||
@@ -57,7 +58,7 @@ class StubRunnerExecutor implements StubFinder {
|
||||
|
||||
private final AvailablePortScanner portScanner;
|
||||
|
||||
private final MessageVerifier<?> contractVerifierMessaging;
|
||||
private final MessageVerifierSender<?> messageVerifierSender;
|
||||
|
||||
private final List<HttpServerStub> serverStubs;
|
||||
|
||||
@@ -65,10 +66,10 @@ class StubRunnerExecutor implements StubFinder {
|
||||
|
||||
private final YamlContractConverter yamlContractConverter = new YamlContractConverter();
|
||||
|
||||
StubRunnerExecutor(AvailablePortScanner portScanner, MessageVerifier<?> contractVerifierMessaging,
|
||||
StubRunnerExecutor(AvailablePortScanner portScanner, MessageVerifierSender<?> messageVerifierSender,
|
||||
List<HttpServerStub> serverStubs) {
|
||||
this.portScanner = portScanner;
|
||||
this.contractVerifierMessaging = contractVerifierMessaging;
|
||||
this.messageVerifierSender = messageVerifierSender;
|
||||
this.serverStubs = serverStubs;
|
||||
}
|
||||
|
||||
@@ -248,11 +249,22 @@ class StubRunnerExecutor implements StubFinder {
|
||||
List<YamlContract> yamlContracts = yamlContractConverter.convertTo(Collections.singleton(groovyDsl));
|
||||
YamlContract contract = yamlContracts.get(0);
|
||||
setMessageType(contract, ContractVerifierMessageMetadata.MessageType.OUTPUT);
|
||||
// TODO: Json is harcoded here
|
||||
this.contractVerifierMessaging.send(
|
||||
JsonOutput
|
||||
.toJson(BodyExtractor.extractClientValueFromBody(body == null ? null : body.getClientValue())),
|
||||
headers == null ? null : headers.asStubSideMap(), outputMessage.getSentTo().getClientValue(), contract);
|
||||
|
||||
Object payload = null;
|
||||
if (body.getClientValue() instanceof FromFileProperty) {
|
||||
FromFileProperty fromFile = (FromFileProperty) body.getClientValue();
|
||||
if (fromFile.isByte()) {
|
||||
payload = fromFile.asBytes();
|
||||
} else {
|
||||
payload = fromFile.asString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
payload = JsonOutput.toJson(BodyExtractor.extractClientValueFromBody(body == null ? null : body.getClientValue()));
|
||||
}
|
||||
|
||||
this.messageVerifierSender.send(payload, headers == null ? null : headers.asStubSideMap(),
|
||||
outputMessage.getSentTo().getClientValue(), contract);
|
||||
}
|
||||
|
||||
private void setMessageType(YamlContract contract, ContractVerifierMessageMetadata.MessageType output) {
|
||||
|
||||
@@ -99,6 +99,54 @@ class StubRunnerExecutorSpec extends Specification {
|
||||
executor.shutdown()
|
||||
}
|
||||
|
||||
def 'should ensure that triggered contracts have properly parsed message body from file as bytes when a message is sent'() {
|
||||
given:
|
||||
StubRunnerExecutor executor = new StubRunnerExecutor(portScanner, new AssertingStubMessages(), [])
|
||||
executor.runStubs(stubRunnerOptions, repository, stub)
|
||||
when:
|
||||
executor.trigger('send_order_bin')
|
||||
then:
|
||||
noExceptionThrown()
|
||||
cleanup:
|
||||
executor.shutdown()
|
||||
}
|
||||
|
||||
def 'should ensure that triggered contracts have properly parsed message body from file as json when a message is sent'() {
|
||||
given:
|
||||
StubRunnerExecutor executor = new StubRunnerExecutor(portScanner, new AssertingStubMessages(), [])
|
||||
executor.runStubs(stubRunnerOptions, repository, stub)
|
||||
when:
|
||||
executor.trigger('send_order_json')
|
||||
then:
|
||||
noExceptionThrown()
|
||||
cleanup:
|
||||
executor.shutdown()
|
||||
}
|
||||
|
||||
def 'should ensure that triggered contracts have properly parsed message body from file as xml when a message is sent'() {
|
||||
given:
|
||||
StubRunnerExecutor executor = new StubRunnerExecutor(portScanner, new AssertingStubMessages(), [])
|
||||
executor.runStubs(stubRunnerOptions, repository, stub)
|
||||
when:
|
||||
executor.trigger('send_order_xml')
|
||||
then:
|
||||
noExceptionThrown()
|
||||
cleanup:
|
||||
executor.shutdown()
|
||||
}
|
||||
|
||||
def 'should ensure that triggered contracts have properly parsed message body from file as text when a message is sent'() {
|
||||
given:
|
||||
StubRunnerExecutor executor = new StubRunnerExecutor(portScanner, new AssertingStubMessages(), [])
|
||||
executor.runStubs(stubRunnerOptions, repository, stub)
|
||||
when:
|
||||
executor.trigger('send_order_csv')
|
||||
then:
|
||||
noExceptionThrown()
|
||||
cleanup:
|
||||
executor.shutdown()
|
||||
}
|
||||
|
||||
def 'should match stub with empty classifier'() {
|
||||
given:
|
||||
def stubConf = new StubConfiguration('groupX', 'artifactX', 'versionX', '')
|
||||
@@ -208,7 +256,9 @@ class StubRunnerExecutorSpec extends Specification {
|
||||
|
||||
@Override
|
||||
<T> void send(T payload, Map<String, Object> headers, String destination, YamlContract contract) {
|
||||
assert !(JsonOutput.toJson(payload).contains("serverValue"))
|
||||
if(payload instanceof String) {
|
||||
assert !(JsonOutput.toJson(payload).contains("serverValue"))
|
||||
}
|
||||
assert headers.entrySet().every { !(it.value.toString().contains("serverValue")) }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2023 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
description 'issue #1864'
|
||||
label 'send_order_bin'
|
||||
input {
|
||||
triggeredBy('sendOrder()')
|
||||
}
|
||||
outputMessage {
|
||||
sentTo 'orderEventsTopic'
|
||||
headers {
|
||||
[
|
||||
header('contentType': 'application/vnd.orderplaced.v1+avro')
|
||||
]
|
||||
}
|
||||
body(fileAsBytes("orderplaced-event.bin"))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2023 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
description 'issue #1864'
|
||||
label 'send_order_json'
|
||||
input {
|
||||
triggeredBy('sendOrderJson()')
|
||||
}
|
||||
outputMessage {
|
||||
sentTo 'orderEventsTopic'
|
||||
headers {
|
||||
[
|
||||
header('contentType': 'application/json')
|
||||
]
|
||||
}
|
||||
body(file("orderplaced-event.json"))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2023 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
description 'issue #1864'
|
||||
label 'send_order_xml'
|
||||
input {
|
||||
triggeredBy('sendOrderXml()')
|
||||
}
|
||||
outputMessage {
|
||||
sentTo 'orderEventsTopic'
|
||||
headers {
|
||||
[
|
||||
header('contentType': 'application/xml')
|
||||
]
|
||||
}
|
||||
body(file("orderplaced-event.xml"))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2023 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
description 'issue #1864'
|
||||
label 'send_order_csv'
|
||||
input {
|
||||
triggeredBy('sendOrderCsv()')
|
||||
}
|
||||
outputMessage {
|
||||
sentTo 'orderEventsTopic'
|
||||
headers {
|
||||
[
|
||||
header('contentType': 'text/plain')
|
||||
]
|
||||
}
|
||||
body(file("orderplaced-event.csv"))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
H505c50a7-0c26-4582-b9ae-bc1c0f65fec10fakeCustomer@example.com<02><>ٳ<EFBFBD>a
|
||||
@@ -0,0 +1,2 @@
|
||||
orderId,customerId,orderCreated
|
||||
505c50a7-0c26-4582-b9ae-bc1c0f65fec1,fakeUser@example.com,orderCreated": "2023-01-30T15:11:00Z
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 71.
|
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"orderId": "505c50a7-0c26-4582-b9ae-bc1c0f65fec1",
|
||||
"customerId": "fakeUser@example.com",
|
||||
"orderCreated": "2023-01-30T15:11:00Z"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<orderPlaced>
|
||||
<orderId>505c50a7-0c26-4582-b9ae-bc1c0f65fec1</orderId>
|
||||
<custmerId>fakeCustomer@example.com</custmerId>
|
||||
<orderPlaced>2023-01-30T15:11:00Z</orderPlaced>
|
||||
</orderPlaced>
|
||||
Reference in New Issue
Block a user