Revert "Merge branch 'master' into 2.0.x"

This reverts commit 63a1981f54, reversing
changes made to 0cca942e86.
This commit is contained in:
Marcin Grzejszczak
2017-12-20 16:31:52 +01:00
parent f69a2f63d0
commit 822dd4b732
200 changed files with 3075 additions and 1690 deletions

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
@@ -18,12 +18,14 @@
<description>Spring Cloud Contract Tests</description>
<modules>
<module>samples-messaging-camel</module>
<module>samples-messaging-spring</module>
<module>samples-messaging-stream</module>
<module>samples-messaging-integration</module>
<module>samples-messaging-amqp</module>
<module>spring-cloud-contract-stub-runner-boot-eureka</module>
<module>spring-cloud-contract-stub-runner-boot-zookeeper</module>
<module>spring-cloud-contract-stub-runner-camel</module>
<module>spring-cloud-contract-stub-runner-context-path</module>
<module>spring-cloud-contract-stub-runner-moco-contract-jar</module>
<module>spring-cloud-contract-stub-runner-moco</module>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-sample-amqp</artifactId>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[3.8.0.201606301005-RELEASE]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
<config>java:com.example.fraud.CamelMessagingApplication</config>
</configs>
<autoconfigs>
</autoconfigs>
<configSets>
</configSets>
</beansProjectDescription>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-sample-camel</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Contract Sample Camel</name>
<description>Spring Cloud Contract Sample Camel</description>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-camel</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-verifier</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2013-2017 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 com.example;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonCreator;
@SuppressWarnings("serial")
public class BookDeleted implements Serializable {
public final String bookName;
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public BookDeleted(String bookName) {
this.bookName = bookName;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2013-2017 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 com.example;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.camel.Exchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class BookDeleter {
private static final Logger log = LoggerFactory.getLogger(BookDeleter.class);
/**
* Scenario for "should generate tests triggered by a message": client side: if sends
* a message to input.messageFrom then message will be sent to output.messageFrom
* server side: will send a message to input, verify the message contents and await
* upon receiving message on the output messageFrom
*/
public void bookDeleted(Exchange exchange) {
BookDeleted bookDeleted = exchange.getIn().getBody(BookDeleted.class);
log.info("Deleting book " + bookDeleted);
this.bookSuccessfulyDeleted.set(true);
log.info("Book successfuly deleted [" + this.bookSuccessfulyDeleted + "]");
}
private AtomicBoolean bookSuccessfulyDeleted = new AtomicBoolean(false);
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2013-2017 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 com.example;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonCreator;
@SuppressWarnings("serial")
public class BookReturned implements Serializable {
public final String bookName;
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2013-2017 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 com.example;
import org.apache.activemq.camel.component.ActiveMQComponent;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.model.dataformat.JsonLibrary;
import org.apache.camel.spring.SpringRouteBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Marcin Grzejszczak
*/
@Configuration
public class BookRouteConfiguration {
@Bean
ActiveMQComponent activeMQComponent(@Value("${activemq.url:vm://localhost?broker.persistent=false}") String url) {
ActiveMQComponent component = new ActiveMQComponent();
component.setBrokerURL(url);
return component;
}
@Bean
RoutesBuilder myRouter(final BookService bookService, final BookDeleter bookDeleter) {
return new SpringRouteBuilder() {
@Override
public void configure() throws Exception {
// scenario 1 - from bean to output
from("direct:start").unmarshal().json(JsonLibrary.Jackson, BookReturned.class).bean(bookService).to("jms:output");
// scenario 2 - from input to output
from("jms:input").unmarshal().json(JsonLibrary.Jackson, BookReturned.class).bean(bookService).to("jms:output");
// scenario 3 - from input to no output
from("jms:delete").unmarshal().json(JsonLibrary.Jackson, BookDeleted.class).bean(bookDeleter);
}
};
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2013-2017 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 com.example;
import org.apache.camel.Exchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class BookService {
private static final Logger log = LoggerFactory.getLogger(BookService.class);
/**
* Scenario for "should generate tests triggered by a method": client side: must have
* a possibility to "trigger" sending of a message to the given messageFrom server
* side: will run the method and await upon receiving message on the output
* messageFrom
*
* Method triggers sending a message to a source
*/
public void returnBook(Exchange exchange) {
BookReturned bookReturned = exchange.getIn().getBody(BookReturned.class);
log.info("Returning book [$bookReturned]");
exchange.getOut().setBody(bookReturned);
exchange.getOut().setHeader("BOOK-NAME", bookReturned.bookName);
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2013-2017 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 com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CamelMessagingApplication {
public static void main(String[] args) {
SpringApplication.run(CamelMessagingApplication.class, args);
}
}

View File

@@ -0,0 +1,159 @@
/*
* Copyright 2013-2017 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 com.example
import javax.inject.Inject
import org.apache.camel.Message
import org.apache.camel.model.ModelCamelContext
import org.junit.BeforeClass
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootContextLoader
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier
import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier
import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper;
import org.springframework.test.annotation.DirtiesContext
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
import spock.util.concurrent.PollingConditions
import com.jayway.jsonpath.DocumentContext
import com.jayway.jsonpath.JsonPath
import com.toomuchcoding.jsonassert.JsonAssertion
/**
* SPIKE ON TESTS FROM NOTES IN MessagingSpec
*/
// Context configuration would end up in base class
@ContextConfiguration(classes = [CamelMessagingApplication], loader = SpringBootContextLoader)
@DirtiesContext
@AutoConfigureMessageVerifier
class CamelMessagingApplicationSpec extends Specification {
// ALL CASES
@Autowired ModelCamelContext camelContext
@Autowired BookDeleter bookDeleter
@Inject MessageVerifier<Message> contractVerifierMessaging
ContractVerifierObjectMapper contractVerifierObjectMapper = new ContractVerifierObjectMapper()
@BeforeClass
static void init() {
System.setProperty("org.apache.activemq.SERIALIZABLE_PACKAGES", "*")
}
def "should work for triggered based messaging"() {
given:
Contract.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('activemq:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
// generated test should look like this:
when:
bookReturnedTriggered()
then:
def response = contractVerifierMessaging.receive('activemq:output')
response.headers.get('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.body))
JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
}
def "should generate tests triggered by a message"() {
given:
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')
}
}
}
// generated test should look like this:
when:
contractVerifierMessaging.send(
contractVerifierObjectMapper.writeValueAsString([bookName: 'foo']),
[sample: 'header'], 'jms:input')
then:
def response = contractVerifierMessaging.receive('jms:output')
response.headers.get('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.body))
JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
}
def "should generate tests without destination, triggered by a message"() {
given:
Contract.make {
label 'some_label'
input {
messageFrom('jms:delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
// generated test should look like this:
when:
contractVerifierMessaging.send(contractVerifierObjectMapper.writeValueAsString([bookName: 'foo']),
[sample: 'header'], 'jms:delete')
then:
noExceptionThrown()
bookWasDeleted()
}
void bookReturnedTriggered() {
camelContext.createProducerTemplate().sendBody('direct:start', '''{"bookName" : "foo" }''')
}
PollingConditions pollingConditions = new PollingConditions()
void bookWasDeleted() {
pollingConditions.eventually {
assert bookDeleter.bookSuccessfulyDeleted.get()
}
}
}

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-sample-integration</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-sample-spring</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-sample-stream</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-amqp</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-boot-eureka</artifactId>
@@ -24,13 +24,13 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<optional>true</optional>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>

View File

@@ -1,4 +1,5 @@
stubrunner:
camel.enabled: false
idsToServiceIds:
fraudDetectionServer: someNameThatShouldMapFraudDetectionServer
server:

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-boot-zookeeper</artifactId>

View File

@@ -28,7 +28,7 @@ import org.springframework.cloud.client.loadbalancer.LoadBalanced
import org.springframework.cloud.contract.stubrunner.StubFinder
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner
import org.springframework.cloud.zookeeper.ZookeeperProperties
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryClient
import org.springframework.cloud.zookeeper.discovery.ZookeeperServiceDiscovery
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.test.annotation.DirtiesContext
@@ -42,7 +42,8 @@ import spock.lang.Specification
*/
@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = ["stubrunner.cloud.stubbed.discovery.enabled=false",
properties = ["stubrunner.camel.enabled=false",
"stubrunner.cloud.stubbed.discovery.enabled=false",
"debug=true"])
@AutoConfigureStubRunner( ids =
["org.springframework.cloud.contract.verifier.stubs:loanIssuance",
@@ -54,7 +55,7 @@ class StubRunnerSpringCloudZookeeperAutoConfigurationSpec extends Specification
@Autowired StubFinder stubFinder
@Autowired @LoadBalanced RestTemplate restTemplate
@Autowired ZookeeperDiscoveryClient zookeeperServiceDiscovery
@Autowired ZookeeperServiceDiscovery zookeeperServiceDiscovery
@BeforeClass
@AfterClass
@@ -75,8 +76,12 @@ class StubRunnerSpringCloudZookeeperAutoConfigurationSpec extends Specification
def 'should have all apps registered in Service Discovery'() {
expect:
!zookeeperServiceDiscovery.getInstances('loanIssuance').empty
!zookeeperServiceDiscovery.getInstances('someNameThatShouldMapFraudDetectionServer').empty
!zookeeperServiceDiscovery.serviceDiscoveryRef.get().queryForInstances('loanIssuance').empty
!zookeeperServiceDiscovery.serviceDiscoveryRef.get().queryForInstances('someNameThatShouldMapFraudDetectionServer').empty
}
def cleanup() {
zookeeperServiceDiscovery?.serviceDiscoveryRef?.get()?.close()
}
@Configuration

View File

@@ -1,4 +1,5 @@
stubrunner:
camel.enabled: false
idsToServiceIds:
fraudDetectionServer: someNameThatShouldMapFraudDetectionServer
server:

View File

@@ -0,0 +1,132 @@
:input_name: jms:input
:output_name: jms:output
=== Stub Runner Camel
Spring Cloud Contract Verifier Stub Runner's messaging module gives you an easy way to
integrate with Apache Camel. For the provided artifacts, it automatically downloads the
stubs and registers the required routes.
==== Adding the Runner to the Project
You can have both Apache Camel and Spring Cloud Contract Stub Runner on the classpath.
Remember to annotate your test class with `@AutoConfigureStubRunner`.
==== Disabling the functionality
If you need to disable this functionality, set the `stubrunner.camel.enabled=false`
property.
Assume that you have the following Maven repository with deployed stubs for the
`camelService` application:
[source,bash,indent=0]
----
└── .m2
└── repository
└── io
└── codearte
└── accurest
└── stubs
└── camelService
├── 0.0.1-SNAPSHOT
│   ├── camelService-0.0.1-SNAPSHOT.pom
│   ├── camelService-0.0.1-SNAPSHOT-stubs.jar
│   └── maven-metadata-local.xml
└── maven-metadata-local.xml
----
Further assume that the stubs contain the following structure:
[source,bash,indent=0]
----
├── META-INF
│   └── MANIFEST.MF
└── repository
├── accurest
│   ├── bookDeleted.groovy
│   ├── bookReturned1.groovy
│   └── bookReturned2.groovy
└── mappings
----
Consider the following contracts (numbered *1*):
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=sample_dsl,indent=0]
----
Now consider *2*
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=sample_dsl_2,indent=0]
----
These examples lend themselves to three scenarios:
* <<camel-scenario-1>>
* <<camel-scenario-2>>
* <<camel-scenario-3>>
[[camel-scenario-1]]
===== Scenario 1 (no input message)
To trigger a message via the `return_book_1` label, use the `StubTigger` interface, as
follows:
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_trigger,indent=0]
----
To listen to the output of the message sent to `{output_name}`:
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_trigger_receive,indent=0]
----
The received message passes the following assertions:
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_trigger_message,indent=0]
----
[[camel-scenario-2]]
===== Scenario 2 (output triggered by input)
Since the route is set for you, you can send a message to the `{output_name}`
destination:
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_send,indent=0]
----
You can listen to the output of the message sent to `{output_name}`:
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_receive,indent=0]
----
The received message passes the following assertions:
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=client_receive_message,indent=0]
----
[[camel-scenario-3]]
===== Scenario 3 (input with no output)
Since the route is set for you, you can send a message to the `{output_name}`
destination:
[source,groovy]
----
include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/camel/CamelStubRunnerSpec.groovy[tags=trigger_no_output,indent=0]
----

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-camel</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Contract Stub Runner Camel</name>
<description>Spring Cloud Contract Stub Runner Camel</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-stub-runner</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner-jetty</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-camel</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.solidsoft.spock</groupId>
<artifactId>spock-global-unroll</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2013-2017 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.stubrunner.messaging.camel
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
@CompileStatic
@EqualsAndHashCode
class BookReturned implements Serializable {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,254 @@
/*
* Copyright 2013-2017 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.stubrunner.messaging.camel
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import org.apache.activemq.camel.component.ActiveMQComponent
import org.apache.activemq.spring.ActiveMQConnectionFactory
import org.apache.camel.CamelContext
import org.apache.camel.Exchange
import org.apache.camel.component.jms.JmsConfiguration
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.test.context.SpringBootContextLoader
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.stubrunner.StubFinder
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.test.context.ContextConfiguration
import spock.lang.IgnoreIf
import spock.lang.Specification
/**
* @author Marcin Grzejszczak
*/
@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)
@SpringBootTest(properties = "debug=true")
@AutoConfigureStubRunner
@IgnoreIf({ os.windows })
class CamelStubRunnerSpec extends Specification {
@Autowired StubFinder stubFinder
@Autowired CamelContext camelContext
def setup() {
// ensure that message were taken from the queue
camelContext.createConsumerTemplate().receive('jms:output', 100)
}
def 'should download the stub and register a route for it'() {
when:
// tag::client_send[]
camelContext.createProducerTemplate().sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header'])
// end::client_send[]
then:
// tag::client_receive[]
Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
// end::client_receive[]
and:
// tag::client_receive_message[]
receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
// end::client_receive_message[]
}
def 'should trigger a message by label'() {
when:
// tag::client_trigger[]
stubFinder.trigger('return_book_1')
// end::client_trigger[]
then:
// tag::client_trigger_receive[]
Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
// end::client_trigger_receive[]
and:
// tag::client_trigger_message[]
receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
// end::client_trigger_message[]
}
def 'should trigger a label for the existing groupId:artifactId'() {
when:
// tag::trigger_group_artifact[]
stubFinder.trigger('org.springframework.cloud.contract.verifier.stubs:camelService', 'return_book_1')
// end::trigger_group_artifact[]
then:
Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
and:
receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
}
def 'should trigger a label for the existing artifactId'() {
when:
// tag::trigger_artifact[]
stubFinder.trigger('camelService', 'return_book_1')
// end::trigger_artifact[]
then:
Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
and:
receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
}
def 'should throw an exception when missing label is passed'() {
when:
stubFinder.trigger('missing label')
then:
thrown(IllegalArgumentException)
}
def 'should throw an exception when missing label and artifactid is passed'() {
when:
stubFinder.trigger('some:service', 'return_book_1')
then:
thrown(IllegalArgumentException)
}
def 'should trigger messages by running all triggers'() {
when:
// tag::trigger_all[]
stubFinder.trigger()
// end::trigger_all[]
then:
Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
and:
receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
}
def 'should trigger a label with no output message'() {
when:
// tag::trigger_no_output[]
camelContext.createProducerTemplate().sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header'])
// end::trigger_no_output[]
then:
noExceptionThrown()
}
def 'should not trigger a message that does not match input'() {
when:
camelContext.createProducerTemplate().sendBodyAndHeaders('jms:input', new BookReturned('notmatching'), [wrong: 'header_value'])
then:
Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 100)
and:
receivedMessage == null
}
private boolean assertThatBodyContainsBookNameFoo(Object payload) {
String objectAsString = payload instanceof String ? payload :
JsonOutput.toJson(payload)
def json = new JsonSlurper().parseText(objectAsString)
return json.bookName == 'foo'
}
@Configuration
@ComponentScan
@EnableAutoConfiguration
static class Config {
@Bean
ActiveMQConnectionFactory activeMQConnectionFactory(@Value('${activemq.url:vm://localhost?broker.persistent=false}') String url) {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL: url)
try {
factory.trustAllPackages = true
} catch (Throwable e) {
}
return factory
}
@Bean
JmsConfiguration jmsConfiguration(ActiveMQConnectionFactory activeMQConnectionFactory) {
return new JmsConfiguration(connectionFactory: activeMQConnectionFactory)
}
@Bean
ActiveMQComponent activeMQComponent(JmsConfiguration jmsConfiguration) {
return new ActiveMQComponent(configuration: jmsConfiguration)
}
}
Contract dsl =
// tag::sample_dsl[]
Contract.make {
label 'return_book_1'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('jms:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
// end::sample_dsl[]
Contract dsl2 =
// tag::sample_dsl_2[]
Contract.make {
label 'return_book_2'
input {
messageFrom('jms:input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('jms:output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
// end::sample_dsl_2[]
Contract dsl3 =
// tag::sample_dsl_3[]
Contract.make {
label 'delete_book'
input {
messageFrom('jms:delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
// end::sample_dsl_3[]
}

View File

@@ -0,0 +1,98 @@
package org.springframework.cloud.contract.stubrunner.messaging.camel
import org.apache.camel.CamelContext
import org.apache.camel.Exchange
import org.apache.camel.builder.ExchangeBuilder
import org.apache.camel.spring.SpringCamelContext
import org.springframework.cloud.contract.spec.Contract
import spock.lang.Specification
class StubRunnerCamelProcessorSpec extends Specification {
CamelContext camelContext = new SpringCamelContext()
Exchange message = ExchangeBuilder.anExchange(camelContext).build()
def noOutputMessageContract = Contract.make {
label 'return_book_2'
input {
messageFrom('bookStorage')
messageBody([
bookId: $(consumer(regex('[0-9]+')), producer('123'))
])
messageHeaders {
header('sample', 'header')
}
}
}
def 'should not process the message if there is no output message'() {
given:
StubRunnerCamelProcessor processor = new StubRunnerCamelProcessor(noOutputMessageContract)
when:
processor.process(message)
then:
noExceptionThrown()
}
def dsl = Contract.make {
label 'return_book_2'
input {
messageFrom('bookStorage')
messageBody([
bookId: $(consumer(regex('[0-9]+')), producer('123'))
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('returnBook')
body([
responseId: $(producer(regex('[0-9]+')), consumer('123'))
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
def 'should process message when it has an output message section'() {
given:
StubRunnerCamelProcessor processor = new StubRunnerCamelProcessor(dsl)
when:
processor.process(message)
then:
message.getIn().getBody(String) == '{"responseId":"123"}'
}
def dslWithRegexInGString = Contract.make {
// Human readable description
description 'Should produce valid sensor data'
// Label by means of which the output message can be triggered
label 'sensor1'
// input to the contract
input {
// the contract will be triggered by a method
triggeredBy('createSensorData()')
}
// output message of the contract
outputMessage {
// destination to which the output message will be sent
sentTo 'sensor-data'
headers {
header('contentType': 'application/json')
}
// the body of the output message
body("""{"id":"${value(producer(regex('[0-9]+')), consumer('99'))}","temperature":"123.45"}""")
}
}
def 'should convert dsl into message with regex in GString'() {
given:
StubRunnerCamelProcessor processor = new StubRunnerCamelProcessor(dslWithRegexInGString)
when:
processor.process(message)
then:
message.getIn().getBody(String) == '''{"id":"99","temperature":"123.45"}'''
}
}

View File

@@ -0,0 +1,5 @@
stubrunner.repositoryRoot: classpath:m2repo/repository/
stubrunner.ids: org.springframework.cloud.contract.verifier.stubs:camelService
server:
port: 0
debug: true

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2017 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.
-->
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud.contract.verifier.stubs</groupId>
<artifactId>camelService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
</project>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2017 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.
-->
<metadata>
<groupId>org.springframework.cloud.contract.verifier.stubs</groupId>
<artifactId>camelService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<versioning>
<snapshot>
<localCopy>true</localCopy>
</snapshot>
<lastUpdated>20160409062112</lastUpdated>
</versioning>
</metadata>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2017 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.
-->
<metadata>
<groupId>org.springframework.cloud.contract.verifier.stubs</groupId>
<artifactId>camelService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<versioning>
<versions>
<version>0.0.1-SNAPSHOT</version>
</versions>
<lastUpdated>20160409062112</lastUpdated>
</versioning>
</metadata>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2017 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.
-->
<metadata>
<groupId>org.springframework.cloud.contract.verifier.stubs</groupId>
<artifactId>camelService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<versioning>
<versions>
<version>0.0.1-SNAPSHOT</version>
</versions>
<lastUpdated>20160409062112</lastUpdated>
</versioning>
</metadata>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-context-path</artifactId>

View File

@@ -2,8 +2,6 @@ package com.example.loan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class Application {
@@ -13,12 +11,3 @@ public class Application {
}
}
@RestController
class CustomController {
@GetMapping("/foo")
String foo() {
return "bar";
}
}

View File

@@ -1,4 +1,2 @@
server:
port: 0
servlet:
context-path: /my-path
server.port: 0
server.context-path: /my-path

View File

@@ -4,9 +4,9 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.contract.stubrunner.StubFinder;
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
import org.springframework.test.annotation.DirtiesContext;
@@ -41,7 +41,7 @@ public class LoanApplicationServiceTests {
@Test
public void shouldStartThisAppWithContextPath() {
String response = new RestTemplate()
.getForObject("http://localhost:" + this.port + "/my-path/foo", String.class);
.getForObject("http://localhost:" + this.port + "/my-path/health", String.class);
assertThat(response).isNotEmpty();
}

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-integration</artifactId>
@@ -16,10 +16,6 @@
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-stub-runner</artifactId>
@@ -33,6 +29,10 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-verifier</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-java-dsl</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-moco-contract-jar</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-moco</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-tests</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>1.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-contract-stub-runner-stream</artifactId>
@@ -36,6 +36,10 @@
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-java-dsl</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View File

@@ -163,8 +163,7 @@ class StreamStubRunnerSpec extends Specification {
private boolean assertJsons(Object payload) {
String objectAsString = payload instanceof String ? payload :
payload instanceof byte[] ? new String(payload)
: JsonOutput.toJson(payload)
JsonOutput.toJson(payload)
def json = new JsonSlurper().parseText(objectAsString)
return json.bookName == 'foo'
}