Skip to content

Commit

Permalink
allow sendMessage to handle body from file (#1867)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
dmfrey authored Mar 14, 2023
1 parent 77b05b6 commit 7bf491c
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@
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;
Expand All @@ -57,18 +58,18 @@ class StubRunnerExecutor implements StubFinder {

private final AvailablePortScanner portScanner;

private final MessageVerifier<?> contractVerifierMessaging;
private final MessageVerifierSender<?> messageVerifierSender;

private final List<HttpServerStub> serverStubs;

private StubServer stubServer;

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;
}

Expand Down Expand Up @@ -248,11 +249,22 @@ private void sendMessage(Contract groovyDsl) {
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', '')
Expand Down Expand Up @@ -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")) }
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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"))
}
}
Original file line number Diff line number Diff line change
@@ -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"))
}
}
Original file line number Diff line number Diff line change
@@ -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"))
}
}
Original file line number Diff line number Diff line change
@@ -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"))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
H505c50a7-0c26-4582-b9ae-bc1c0f65fec10fakeCustomer@example.com��ٳ�a
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
orderId,customerId,orderCreated
505c50a7-0c26-4582-b9ae-bc1c0f65fec1,fakeUser@example.com,orderCreated": "2023-01-30T15:11:00Z
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"orderId": "505c50a7-0c26-4582-b9ae-bc1c0f65fec1",
"customerId": "fakeUser@example.com",
"orderCreated": "2023-01-30T15:11:00Z"
}
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit 7bf491c

Please sign in to comment.