diff --git a/README.adoc b/README.adoc
index fc263f9606..16d4f9b610 100644
--- a/README.adoc
+++ b/README.adoc
@@ -305,7 +305,7 @@ with __Contract Definition Language__ (DSL). Contract definitions are used to pr
* JSON stub definitions to be used by WireMock when doing integration testing on the client code (__client tests__).
Test code must still be written by hand, test data is produced by Spring Cloud Contract Verifier.
-* Messaging routes if you're using one. We're integrating with Spring Integration, Spring Cloud Stream and Apache Camel. You can however set your own integrations if you want to
+* Messaging routes if you're using one. We're integrating with Spring Integration, Spring Cloud Stream, Spring AMQP and Apache Camel. You can however set your own integrations if you want to
* Acceptance tests (in JUnit or Spock) used to verify if server-side implementation of the API is compliant with the contract (__server tests__).
Full test is generated by Spring Cloud Contract Verifier.
diff --git a/docs/src/main/asciidoc/verifier/introduction.adoc b/docs/src/main/asciidoc/verifier/introduction.adoc
index babec72446..60ae5a6b6e 100644
--- a/docs/src/main/asciidoc/verifier/introduction.adoc
+++ b/docs/src/main/asciidoc/verifier/introduction.adoc
@@ -11,7 +11,7 @@ with __Contract Definition Language__ (DSL). Contract definitions are used to pr
* JSON stub definitions to be used by WireMock when doing integration testing on the client code (__client tests__).
Test code must still be written by hand, test data is produced by Spring Cloud Contract Verifier.
-* Messaging routes if you're using one. We're integrating with Spring Integration, Spring Cloud Stream and Apache Camel. You can however set your own integrations if you want to
+* Messaging routes if you're using one. We're integrating with Spring Integration, Spring Cloud Stream, Spring AMQP and Apache Camel. You can however set your own integrations if you want to
* Acceptance tests (in JUnit or Spock) used to verify if server-side implementation of the API is compliant with the contract (__server tests__).
Full test is generated by Spring Cloud Contract Verifier.
diff --git a/docs/src/main/asciidoc/verifier/messaging.adoc b/docs/src/main/asciidoc/verifier/messaging.adoc
index e51b4a1d18..19ed1da0ae 100644
--- a/docs/src/main/asciidoc/verifier/messaging.adoc
+++ b/docs/src/main/asciidoc/verifier/messaging.adoc
@@ -5,11 +5,12 @@ All of our integrations are working with Spring but you can also create one your
==== Integrations
-You can use one of the three integration configurations:
+You can use one of the four integration configurations:
- Apache Camel
- Spring Integration
- Spring Cloud Stream
+- Spring AMQP
Since we're using Spring Boot then if you have added one of the aforementioned libraries
to the classpath then automatically all the messaging configuration will be set up.
diff --git a/docs/src/main/asciidoc/verifier/stubrunner_msg.adoc b/docs/src/main/asciidoc/verifier/stubrunner_msg.adoc
index 4202b35b3c..776bdff84c 100644
--- a/docs/src/main/asciidoc/verifier/stubrunner_msg.adoc
+++ b/docs/src/main/asciidoc/verifier/stubrunner_msg.adoc
@@ -5,6 +5,7 @@ Stub Runner has the functionality to run the published stubs in memory. It can i
- Spring Integration
- Spring Cloud Stream
- Apache Camel
+- Spring AMQP
It also provides points of entry to integrate with any other solution on the market.
@@ -53,4 +54,6 @@ include::{tests_path}/spring-cloud-contract-stub-runner-camel/README.adoc[]
include::{tests_path}/spring-cloud-contract-stub-runner-integration/README.adoc[]
-include::{tests_path}/spring-cloud-contract-stub-runner-stream/README.adoc[]
\ No newline at end of file
+include::{tests_path}/spring-cloud-contract-stub-runner-stream/README.adoc[]
+
+include::{tests_path}/spring-cloud-contract-stub-runner-amqp/README.adoc[]
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index c7c962e46d..97c67f4642 100644
--- a/pom.xml
+++ b/pom.xml
@@ -104,6 +104,16 @@
spock-global-unroll
0.5.0
+
+ org.springframework.amqp
+ spring-rabbit
+ 1.6.2.RELEASE
+
+
+ org.mockito
+ mockito-core
+ 1.10.19
+
org.springframework.cloud
spring-cloud-contract-dependencies
diff --git a/spring-cloud-contract-verifier/pom.xml b/spring-cloud-contract-verifier/pom.xml
index a879c0c37d..8c97973a73 100644
--- a/spring-cloud-contract-verifier/pom.xml
+++ b/spring-cloud-contract-verifier/pom.xml
@@ -36,6 +36,11 @@
spring-cloud-stream-test-support
true
+
+ org.springframework.amqp
+ spring-rabbit
+ true
+
javax.inject
javax.inject
@@ -90,7 +95,6 @@
org.springframework.boot
spring-boot-starter-test
- test
org.slf4j
diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/ContractVerifierAmqpAutoConfiguration.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/ContractVerifierAmqpAutoConfiguration.java
new file mode 100644
index 0000000000..1e05c32cb6
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/ContractVerifierAmqpAutoConfiguration.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+package org.springframework.cloud.contract.verifier.messaging.amqp;
+
+import org.mockito.Mockito;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
+import org.springframework.amqp.support.SimpleAmqpHeaderMapper;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.amqp.support.converter.MessagingMessageConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
+import org.springframework.cloud.contract.verifier.messaging.integration.ContractVerifierIntegrationConfiguration;
+import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage;
+import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging;
+import org.springframework.cloud.contract.verifier.messaging.stream.ContractVerifierStreamAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Configuration setting up {@link MessageVerifier} for use with plain spring-rabbit/spring-amqp
+ *
+ * @author Mathias Düsterhöft
+ * @since 1.0.2
+ */
+@Configuration
+@ConditionalOnClass({Message.class, RabbitTemplate.class, Mockito.class})
+@ConditionalOnMissingClass("org.springframework.integration.core.MessageSource")
+@AutoConfigureBefore(ContractVerifierIntegrationConfiguration.class)
+@AutoConfigureAfter(ContractVerifierStreamAutoConfiguration.class)
+public class ContractVerifierAmqpAutoConfiguration {
+
+ @SpyBean
+ private RabbitTemplate rabbitTemplate;
+
+ @Autowired(required = false)
+ private MessageListenerAdapter messageListenerAdapter;
+
+ @Bean
+ @ConditionalOnMissingBean
+ public MessageVerifier contractVerifierMessageExchange() {
+ return new SpringAmqpStubMessages(this.rabbitTemplate, this.messageListenerAdapter);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ContractVerifierMessaging contractVerifierMessaging(
+ MessageVerifier exchange) {
+ return new ContractVerifierHelper(exchange, this.rabbitTemplate.getMessageConverter());
+ }
+}
+
+class ContractVerifierHelper extends ContractVerifierMessaging {
+
+ private final MessageConverter messageConverter;
+
+ public ContractVerifierHelper(MessageVerifier exchange, MessageConverter messageConverter) {
+ super(exchange);
+ this.messageConverter = messageConverter;
+ }
+
+ @Override
+ protected ContractVerifierMessage convert(Message message) {
+ MessagingMessageConverter messageConverter = new MessagingMessageConverter(this.messageConverter, new SimpleAmqpHeaderMapper());
+ org.springframework.messaging.Message> messagingMessage = (org.springframework.messaging.Message>) messageConverter.fromMessage(message);
+ return new ContractVerifierMessage(messagingMessage.getPayload(), messagingMessage.getHeaders());
+ }
+}
+
diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/RabbitMockConnectionFactoryAutoConfiguration.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/RabbitMockConnectionFactoryAutoConfiguration.java
new file mode 100644
index 0000000000..9f33d5b49d
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/RabbitMockConnectionFactoryAutoConfiguration.java
@@ -0,0 +1,52 @@
+package org.springframework.cloud.contract.verifier.messaging.amqp;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.ExecutorService;
+
+import org.mockito.Mockito;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.rabbitmq.client.Channel;
+import com.rabbitmq.client.Connection;
+
+/**
+ * Spring rabbit test utility that provides a mock ConnectionFactory to avoid having to connect against a running broker.
+ *
+ * Set verifier.amqp.mockConnection=true to enable the mocked ConnectionFactory
+ *
+ * @author Mathias Düsterhöft
+ * @since 1.0.2
+ */
+@Configuration
+@ConditionalOnClass({Message.class, RabbitTemplate.class, Mockito.class})
+@ConditionalOnMissingClass("org.springframework.integration.core.MessageSource")
+@AutoConfigureAfter(ContractVerifierAmqpAutoConfiguration.class)
+@ConditionalOnProperty(value = "verifier.amqp.mockConnection", havingValue = "true", matchIfMissing = true)
+public class RabbitMockConnectionFactoryAutoConfiguration {
+
+ @Bean
+ public ConnectionFactory connectionFactory() {
+ com.rabbitmq.client.ConnectionFactory mockConnectionFactory = mock(com.rabbitmq.client.ConnectionFactory.class);
+ Connection mockConnection = mock(Connection.class);
+ Channel mockChannel = mock(Channel.class);
+ try {
+ when(mockConnectionFactory.newConnection((ExecutorService) null)).thenReturn(mockConnection);
+ when(mockConnection.isOpen()).thenReturn(true);
+ when(mockConnection.createChannel()).thenReturn(mockChannel);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return new CachingConnectionFactory(mockConnectionFactory);
+ }
+}
diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/SpringAmqpStubMessages.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/SpringAmqpStubMessages.java
new file mode 100644
index 0000000000..9329f631cc
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/messaging/amqp/SpringAmqpStubMessages.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+package org.springframework.cloud.contract.verifier.messaging.amqp;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mockingDetails;
+import static org.mockito.Mockito.verify;
+import static org.springframework.amqp.support.converter.DefaultClassMapper.DEFAULT_CLASSID_FIELD_NAME;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.mockito.ArgumentCaptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessagePropertiesBuilder;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
+import org.springframework.amqp.rabbit.support.CorrelationData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.contract.verifier.messaging.MessageVerifier;
+import org.springframework.util.Assert;
+
+/**
+ * {@link MessageVerifier} implementation to integrate with plain spring-amqp/spring-rabbit.
+ * It is meant to be used without interacting with a running bus.
+ *
+ * It relies on the RabbitTemplate to be a spy to be able to capture send messages.
+ *
+ * Messages are not sent to the bus - but are handed over to the {@link MessageListenerAdapter} which
+ * allows us to test the full deserialization and listener invocation.
+ *
+ * @author Mathias Düsterhöft
+ * @since 1.0.2
+ */
+public class SpringAmqpStubMessages implements
+ MessageVerifier {
+
+ private static final Logger log = LoggerFactory.getLogger(SpringAmqpStubMessages.class);
+
+ private final RabbitTemplate rabbitTemplate;
+
+ private final MessageListenerAdapter messageListenerAdapter;
+
+ @Autowired
+ public SpringAmqpStubMessages(RabbitTemplate rabbitTemplate, MessageListenerAdapter messageListenerAdapter) {
+ Assert.notNull(rabbitTemplate);
+ Assert.isTrue(mockingDetails(rabbitTemplate).isSpy() || mockingDetails(rabbitTemplate).isMock()); //we get send messages by capturing arguments on the spy
+ this.rabbitTemplate = rabbitTemplate;
+ this.messageListenerAdapter = messageListenerAdapter;
+ }
+
+ @Override
+ public void send(T payload, Map headers, String destination) {
+ Message message = org.springframework.amqp.core.MessageBuilder
+ .withBody(((String) payload).getBytes())
+ .andProperties(
+ MessagePropertiesBuilder.newInstance()
+ .setContentType((String) headers.get("contentType"))
+ .copyHeaders(headers).build())
+ .build();
+ if (headers.containsKey(DEFAULT_CLASSID_FIELD_NAME)) {
+ message.getMessageProperties().setHeader(DEFAULT_CLASSID_FIELD_NAME, headers.get(DEFAULT_CLASSID_FIELD_NAME));
+ }
+ send(message, destination);
+ }
+
+ @Override
+ public void send(Message message, String destination) {
+ if (this.messageListenerAdapter == null) {
+ throw new IllegalStateException("no MessageListenerAdapter wired - cannot send message");
+ }
+ this.messageListenerAdapter.onMessage(message);
+ }
+
+ @Override
+ public Message receive(String destination, long timeout, TimeUnit timeUnit) {
+ ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(this.rabbitTemplate).send(eq(destination), anyString(), messageCaptor.capture(), any(CorrelationData.class));
+
+ if (messageCaptor.getAllValues().isEmpty()) {
+ log.info("no messages found on destination {}", destination);
+ return null;
+ } else if (messageCaptor.getAllValues().size() > 1) {
+ log.info("multiple messages found on destination {} returning last one - {}", destination);
+ return messageCaptor.getValue();
+ }
+ return messageCaptor.getValue();
+ }
+
+ @Override
+ public Message receive(String destination) {
+ return receive(destination, 5, TimeUnit.SECONDS);
+ }
+
+}
diff --git a/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories b/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
index 0d1daef226..0e6be1c75d 100644
--- a/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories
@@ -2,5 +2,7 @@
org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier=\
org.springframework.cloud.contract.verifier.messaging.stream.ContractVerifierStreamAutoConfiguration,\
org.springframework.cloud.contract.verifier.messaging.integration.ContractVerifierIntegrationConfiguration,\
+org.springframework.cloud.contract.verifier.messaging.amqp.ContractVerifierAmqpAutoConfiguration,\
+org.springframework.cloud.contract.verifier.messaging.amqp.RabbitMockConnectionFactoryAutoConfiguration,\
org.springframework.cloud.contract.verifier.messaging.camel.ContractVerifierCamelConfiguration,\
org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierAutoConfiguration
\ No newline at end of file
diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/messaging/amqp/ContractVerifierHelperSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/messaging/amqp/ContractVerifierHelperSpec.groovy
new file mode 100644
index 0000000000..6665f1e503
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/messaging/amqp/ContractVerifierHelperSpec.groovy
@@ -0,0 +1,33 @@
+package org.springframework.cloud.contract.verifier.messaging.amqp
+
+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")
+ }
+}
diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/messaging/amqp/SpringAmqpStubMessagesSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/messaging/amqp/SpringAmqpStubMessagesSpec.groovy
new file mode 100644
index 0000000000..776c464bc3
--- /dev/null
+++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/messaging/amqp/SpringAmqpStubMessagesSpec.groovy
@@ -0,0 +1,39 @@
+package org.springframework.cloud.contract.verifier.messaging.amqp
+
+import com.google.common.collect.ImmutableMap
+import org.mockito.ArgumentCaptor
+import org.springframework.amqp.core.Message
+import org.springframework.amqp.rabbit.core.RabbitTemplate
+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)
+ MessageListenerAdapter messageListenerAdapter = Mock(MessageListenerAdapter.class)
+
+ def "should send amqp message with type id"() {
+ given:
+ String payload = '''{"name":"some"}'''
+ ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class)
+ SpringAmqpStubMessages messageVerifier = new SpringAmqpStubMessages(rabbitTemplate, messageListenerAdapter)
+ when:
+ messageVerifier.send(payload,
+ ImmutableMap.builder()
+ .put(DEFAULT_CLASSID_FIELD_NAME, "org.example.Some")
+ .put("contentType", CONTENT_TYPE_JSON)
+ .build(),
+ "test-exchange")
+ then:
+ 1 * messageListenerAdapter.onMessage({
+ it.getMessageProperties().getContentType() == CONTENT_TYPE_JSON &&
+ it.getMessageProperties().getHeaders().get(DEFAULT_CLASSID_FIELD_NAME) == "org.example.Some"
+ })
+ }
+}
diff --git a/tests/pom.xml b/tests/pom.xml
index ef64f01973..da9baafb6e 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -22,12 +22,14 @@
samples-messaging-spring
samples-messaging-stream
samples-messaging-integration
+ samples-messaging-amqp
spring-cloud-contract-stub-runner-boot-eureka
spring-cloud-contract-stub-runner-boot-zookeeper
spring-cloud-contract-stub-runner-camel
spring-cloud-contract-stub-runner-context-path
spring-cloud-contract-stub-runner-integration
spring-cloud-contract-stub-runner-stream
+ spring-cloud-contract-stub-runner-amqp
diff --git a/tests/samples-messaging-amqp/pom.xml b/tests/samples-messaging-amqp/pom.xml
new file mode 100644
index 0000000000..44efa49dce
--- /dev/null
+++ b/tests/samples-messaging-amqp/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud
+ spring-cloud-contract-tests
+ 1.0.1.BUILD-SNAPSHOT
+ ..
+
+ spring-cloud-contract-sample-amqp
+ jar
+ Spring Cloud Contract Sample Spring Amqp
+ Spring Cloud Contract Sample Spring Amqp Rabbit
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+ org.springframework.cloud
+ spring-cloud-contract-verifier
+ test
+
+
+ org.spockframework
+ spock-spring
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.codehaus.gmavenplus
+ gmavenplus-plugin
+
+
+
+
diff --git a/tests/samples-messaging-amqp/src/main/java/com/example/AmqpMessagingApplication.java b/tests/samples-messaging-amqp/src/main/java/com/example/AmqpMessagingApplication.java
new file mode 100644
index 0000000000..251f9f738d
--- /dev/null
+++ b/tests/samples-messaging-amqp/src/main/java/com/example/AmqpMessagingApplication.java
@@ -0,0 +1,46 @@
+package com.example;
+
+import static org.springframework.amqp.core.MessageProperties.CONTENT_TYPE_JSON;
+
+import org.springframework.amqp.core.Exchange;
+import org.springframework.amqp.core.TopicExchange;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.support.converter.ContentTypeDelegatingMessageConverter;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@SpringBootApplication
+public class AmqpMessagingApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(AmqpMessagingApplication.class, args);
+ }
+
+ @Bean
+ public MessageConverter messageConverter(ObjectMapper objectMapper) {
+ final Jackson2JsonMessageConverter jsonMessageConverter = new Jackson2JsonMessageConverter();
+ jsonMessageConverter.setJsonObjectMapper(objectMapper);
+ jsonMessageConverter.setCreateMessageIds(true);
+ final ContentTypeDelegatingMessageConverter messageConverter = new ContentTypeDelegatingMessageConverter(jsonMessageConverter);
+ messageConverter.addDelegate(CONTENT_TYPE_JSON, jsonMessageConverter);
+ return messageConverter;
+ }
+
+ @Bean
+ public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
+ RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
+ rabbitTemplate.setMessageConverter(messageConverter);
+ return rabbitTemplate;
+ }
+
+ @Bean
+ public Exchange testExchange() {
+ return new TopicExchange("test-exchange");
+ }
+}
diff --git a/tests/samples-messaging-amqp/src/main/java/com/example/Book.java b/tests/samples-messaging-amqp/src/main/java/com/example/Book.java
new file mode 100644
index 0000000000..5e0832cb90
--- /dev/null
+++ b/tests/samples-messaging-amqp/src/main/java/com/example/Book.java
@@ -0,0 +1,17 @@
+package com.example;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+
+public class Book {
+
+ private String name;
+
+ @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+ public Book(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+}
diff --git a/tests/samples-messaging-amqp/src/main/java/com/example/MessagePublisher.java b/tests/samples-messaging-amqp/src/main/java/com/example/MessagePublisher.java
new file mode 100644
index 0000000000..36890870a3
--- /dev/null
+++ b/tests/samples-messaging-amqp/src/main/java/com/example/MessagePublisher.java
@@ -0,0 +1,23 @@
+package com.example;
+
+import org.springframework.amqp.core.Exchange;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MessagePublisher {
+
+ private final RabbitTemplate rabbitTemplate;
+
+ private final Exchange exchange;
+ @Autowired
+ public MessagePublisher(RabbitTemplate rabbitTemplate, Exchange exchange) {
+ this.rabbitTemplate = rabbitTemplate;
+ this.exchange = exchange;
+ }
+
+ public void sendMessage(Book book) {
+ this.rabbitTemplate.convertAndSend(this.exchange.getName(), "routingkey", book);
+ }
+}
diff --git a/tests/samples-messaging-amqp/src/test/groovy/com/example/AmqpMessagingApplicationSpec.groovy b/tests/samples-messaging-amqp/src/test/groovy/com/example/AmqpMessagingApplicationSpec.groovy
new file mode 100644
index 0000000000..19f8ce482a
--- /dev/null
+++ b/tests/samples-messaging-amqp/src/test/groovy/com/example/AmqpMessagingApplicationSpec.groovy
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+package com.example
+
+import com.jayway.jsonpath.DocumentContext
+import com.jayway.jsonpath.JsonPath
+import com.toomuchcoding.jsonassert.JsonAssertion
+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.boot.AutoConfigureMessageVerifier
+import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging
+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 javax.inject.Inject
+// Context configuration would end up in base class
+@ContextConfiguration(classes = [AmqpMessagingApplication], loader = SpringBootContextLoader)
+@DirtiesContext
+@AutoConfigureMessageVerifier
+public class AmqpMessagingApplicationSpec extends Specification {
+
+ // ALL CASES
+ @Inject ContractVerifierMessaging contractVerifierMessaging
+ @Inject ContractVerifierObjectMapper contractVerifierObjectMapper
+
+ def "should work for triggered based messaging"() {
+ given:
+ def dsl = Contract.make {
+ // Human readable description
+ description 'Some description'
+ // Label by means of which the output message can be triggered
+ label 'some_label'
+ // input to the contract
+ input {
+ // the contract will be triggered by a method
+ triggeredBy('publishBook()')
+ }
+ // output message of the contract
+ outputMessage {
+ // destination to which the output message will be sent
+ sentTo('test-exchange')
+ // the body of the output message
+ body('''{ "name" : "some" }''')
+ // the headers of the output message
+ headers {
+ header('contentType', 'application/json')
+ header('__TypeId__', 'com.example.Book')
+ }
+ }
+ }
+ // generated test should look like this:
+ when:
+ publishBook()
+ then:
+ def response = contractVerifierMessaging.receive('test-exchange')
+ response.headers.get('contentType') == 'application/json'
+ and:
+ DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
+ JsonAssertion.assertThat(parsedJson).field('name').isEqualTo('some')
+ }
+
+ // BASE CLASS WOULD HAVE THIS:
+
+ @Autowired MessagePublisher messagePublisher
+
+ void publishBook() {
+ this.messagePublisher.sendMessage(new Book("some"))
+ }
+}
\ No newline at end of file
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/README.adoc b/tests/spring-cloud-contract-stub-runner-amqp/README.adoc
new file mode 100644
index 0000000000..deb3b59373
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/README.adoc
@@ -0,0 +1,84 @@
+=== Stub Runner Spring AMQP
+
+Spring Cloud Contract Verifier Stub Runner's messaging module provides an easy way to integrate with Spring AMQP's Rabbit Template.
+For the provided artifacts it will automatically download the stubs and register the required
+routes.
+
+The integration tries to work standalone, that is without interaction with a running RabbitMQ message broker. It expects a `RabbitTemplate` on the application context and uses it as a spring boot test `@SpyBean`.
+Thus it can use the mockito spy functionality to verify and introspect messages sent by the application.
+
+IMPORTANT: In the current status of the implementation tries to find a `MessageListenerAdapter` on the application context to send messages into the application, because we want to avoid interacting with a running bus.
+Using annotation driven listener endpoints (e.g. `@RabbitListener` annotated listener methods) is currently not supported.
+
+==== Adding it to the project
+
+It's enough to have both Spring AMQP and Spring Cloud Contract Stub Runner on classpath.
+Remember to annotate your test class with `@AutoConfigureMessageVerifier`.
+
+==== Examples
+
+===== Stubs structure
+
+Let us assume that we have the following Maven repository with a deployed stubs for the
+`spring-cloud-contract-amqp-test` application.
+
+[source,bash,indent=0]
+----
+└── .m2
+ └── repository
+ └── com
+ └── example
+ └── spring-cloud-contract-amqp-test
+ ├── 0.4.0-SNAPSHOT
+ │ ├── spring-cloud-contract-amqp-test-0.4.0-SNAPSHOT.pom
+ │ ├── spring-cloud-contract-amqp-test-0.4.0-SNAPSHOT-stubs.jar
+ │ └── maven-metadata-local.xml
+ └── maven-metadata-local.xml
+----
+
+And the stubs contain the following structure:
+
+[source,bash,indent=0]
+----
+├── META-INF
+│ └── MANIFEST.MF
+└── contracts
+ └── shouldProduceValidPersonData.groovy
+----
+
+Let's consider the following contract:
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/amqp/AmqpStubRunnerSpec.groovy[tags=amqp_contract,indent=0]
+----
+
+
+and the following Spring configuration:
+
+[source,yaml]
+----
+include::src/test/resources/application.yml[]
+----
+
+===== Triggering the message
+
+So to trigger a message using the contract above we'll use the `StubTrigger` interface as follows.
+
+[source,groovy]
+----
+include::src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/amqp/AmqpStubRunnerSpec.groovy[tags=client_trigger,indent=0]
+----
+
+===== Spring AMQP Test Configuration
+
+In order to avoid that Spring AMQP is trying to connect to a running broker during our tests we configure a mock `ConnectionFactory`.
+
+To disable the mocked ConnectionFactory set the property `verifier.amqp.mockConnection=false`
+
+[source,yaml]
+----
+verifier:
+ amqp:
+ mockConnection: false
+----
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/pom.xml b/tests/spring-cloud-contract-stub-runner-amqp/pom.xml
new file mode 100644
index 0000000000..c55173d089
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/pom.xml
@@ -0,0 +1,81 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud
+ spring-cloud-contract-tests
+ 1.0.1.BUILD-SNAPSHOT
+ ..
+
+ spring-cloud-contract-stub-runner-amqp
+ jar
+ Spring Cloud Contract Stub Runner AMQP
+ Spring Cloud Contract Stub Runner AMQP
+
+ 1.8
+
+
+
+ org.springframework.cloud
+ spring-cloud-contract-stub-runner
+
+
+ org.springframework.cloud
+ spring-cloud-starter-contract-stub-runner-jetty
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-contract-verifier
+
+
+ org.springframework.amqp
+ spring-rabbit
+
+
+ junit
+ junit
+ test
+
+
+ org.spockframework
+ spock-core
+ test
+
+
+ org.spockframework
+ spock-spring
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ test
+
+
+ info.solidsoft.spock
+ spock-global-unroll
+ test
+
+
+
+
+
+ org.codehaus.gmavenplus
+ gmavenplus-plugin
+
+
+
+ testCompile
+
+
+
+
+
+
+
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/AmqpMessagingApplication.java b/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/AmqpMessagingApplication.java
new file mode 100644
index 0000000000..0ea154052b
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/AmqpMessagingApplication.java
@@ -0,0 +1,52 @@
+package org.springframework.cloud.contract.stubrunner.messaging.amqp;
+
+import static org.springframework.amqp.core.MessageProperties.CONTENT_TYPE_JSON;
+
+import org.springframework.amqp.core.Exchange;
+import org.springframework.amqp.core.TopicExchange;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
+import org.springframework.amqp.support.converter.ContentTypeDelegatingMessageConverter;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@SpringBootApplication
+public class AmqpMessagingApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(AmqpMessagingApplication.class, args);
+ }
+
+ @Bean
+ public MessageConverter messageConverter(ObjectMapper objectMapper) {
+ final Jackson2JsonMessageConverter jsonMessageConverter = new Jackson2JsonMessageConverter();
+ jsonMessageConverter.setJsonObjectMapper(objectMapper);
+ jsonMessageConverter.setCreateMessageIds(true);
+ final ContentTypeDelegatingMessageConverter messageConverter = new ContentTypeDelegatingMessageConverter(jsonMessageConverter);
+ messageConverter.addDelegate(CONTENT_TYPE_JSON, jsonMessageConverter);
+ return messageConverter;
+ }
+
+ @Bean
+ public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
+ RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
+ rabbitTemplate.setMessageConverter(messageConverter);
+ return rabbitTemplate;
+ }
+
+ @Bean
+ public Exchange testExchange() {
+ return new TopicExchange("test-exchange");
+ }
+
+ @Bean
+ public MessageListenerAdapter messageListenerAdapter(MessageSubscriber messageSubscriber, MessageConverter messageConverter) {
+ return new MessageListenerAdapter(messageSubscriber, messageConverter);
+ }
+}
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/MessageSubscriber.java b/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/MessageSubscriber.java
new file mode 100644
index 0000000000..2722bde351
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/MessageSubscriber.java
@@ -0,0 +1,11 @@
+package org.springframework.cloud.contract.stubrunner.messaging.amqp;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class MessageSubscriber {
+
+ public void handleMessage(Person person) {
+
+ }
+}
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/Person.java b/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/Person.java
new file mode 100644
index 0000000000..87f6286491
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/main/java/org/springframework/cloud/contract/stubrunner/messaging/amqp/Person.java
@@ -0,0 +1,23 @@
+package org.springframework.cloud.contract.stubrunner.messaging.amqp;
+
+public class Person {
+
+ private Integer id;
+ private String name;
+
+ public Integer getId() {
+ return this.id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/amqp/AmqpStubRunnerSpec.groovy b/tests/spring-cloud-contract-stub-runner-amqp/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/amqp/AmqpStubRunnerSpec.groovy
new file mode 100644
index 0000000000..b941ca4785
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/amqp/AmqpStubRunnerSpec.groovy
@@ -0,0 +1,67 @@
+package org.springframework.cloud.contract.stubrunner.messaging.amqp
+
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootContextLoader
+import org.springframework.boot.test.mock.mockito.SpyBean
+import org.springframework.cloud.contract.spec.Contract
+import org.springframework.cloud.contract.stubrunner.StubTrigger
+import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner
+import org.springframework.test.context.ContextConfiguration
+import spock.lang.Specification
+
+import static org.mockito.BDDMockito.then
+
+@ContextConfiguration(classes = [AmqpMessagingApplication], loader = SpringBootContextLoader)
+@AutoConfigureStubRunner
+class AmqpStubRunnerSpec extends Specification {
+
+ @Autowired
+ StubTrigger stubTrigger
+
+ @SpyBean
+ MessageSubscriber messageSubscriber
+
+ @Captor
+ ArgumentCaptor personArgumentCaptor
+
+ def "should trigger stub amqp message"() {
+ given:
+ // tag::amqp_contract[]
+
+ Contract.make {
+ // Human readable description
+ description 'Should produce valid person data'
+ // Label by means of which the output message can be triggered
+ label 'contract-test.person.created.event'
+ // input to the contract
+ input {
+ // the contract will be triggered by a method
+ triggeredBy('createPerson()')
+ }
+ // output message of the contract
+ outputMessage {
+ // destination to which the output message will be sent
+ sentTo 'contract-test.exchange'
+ headers {
+ header('contentType': 'application/json')
+ header('__TypeId__': 'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person')
+ }
+ // the body of the output message
+ body ([
+ id: $(consumer(9), producer(regex("[0-9]+"))),
+ name: "me"
+ ])
+ }
+ }
+ // end::amqp_contract[]
+ when:
+ // tag::client_trigger[]
+ stubTrigger.trigger("contract-test.person.created.event")
+ // end::client_trigger[]
+ then:
+ then(messageSubscriber).should().handleMessage(personArgumentCaptor.capture())
+ personArgumentCaptor.value.name != null
+ }
+}
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/application.yml b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/application.yml
new file mode 100644
index 0000000000..4a5df9496a
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/application.yml
@@ -0,0 +1,2 @@
+stubrunner.repositoryRoot: classpath:m2repo/repository/
+stubrunner.ids: org.springframework.cloud.contract.verifier.stubs.amqp:spring-cloud-contract-amqp-test:0.4.0-SNAPSHOT:stubs
\ No newline at end of file
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/maven-metadata-local.xml b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/maven-metadata-local.xml
new file mode 100644
index 0000000000..91c6038b31
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/maven-metadata-local.xml
@@ -0,0 +1,12 @@
+
+
+ org.springframework.cloud.contract.verifier.stubs.amqp
+ spring-cloud-contract-amqp-test
+ 0.4.0-SNAPSHOT
+
+
+ true
+
+ 20161007155639
+
+
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/spring-cloud-contract-amqp-test-0.4.0-SNAPSHOT-stubs.jar b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/spring-cloud-contract-amqp-test-0.4.0-SNAPSHOT-stubs.jar
new file mode 100644
index 0000000000..2fa845f66b
Binary files /dev/null and b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/spring-cloud-contract-amqp-test-0.4.0-SNAPSHOT-stubs.jar differ
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/spring-cloud-contract-amqp-test-0.4.0-SNAPSHOT.pom b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/spring-cloud-contract-amqp-test-0.4.0-SNAPSHOT.pom
new file mode 100644
index 0000000000..48e29044d6
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/0.4.0-SNAPSHOT/spring-cloud-contract-amqp-test-0.4.0-SNAPSHOT.pom
@@ -0,0 +1,25 @@
+
+
+
+
+ 4.0.0
+ org.springframework.cloud.contract.verifier.stubs.amqp
+ spring-cloud-contract-amqp-test
+ 0.4.0-SNAPSHOT
+ pom
+
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/maven-metadata-local.xml b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/maven-metadata-local.xml
new file mode 100644
index 0000000000..3df4f51931
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/maven-metadata-local.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ org.springframework.cloud.contract.verifier.stubs.amqp
+ spring-cloud-contract-amqp-test
+ 0.4.0-SNAPSHOT
+
+
+ 0.4.0-SNAPSHOT
+
+ 20160409062112
+
+
diff --git a/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/maven-metadata.xml b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/maven-metadata.xml
new file mode 100644
index 0000000000..3df4f51931
--- /dev/null
+++ b/tests/spring-cloud-contract-stub-runner-amqp/src/test/resources/m2repo/repository/org/springframework/cloud/contract/verifier/stubs/amqp/spring-cloud-contract-amqp-test/maven-metadata.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ org.springframework.cloud.contract.verifier.stubs.amqp
+ spring-cloud-contract-amqp-test
+ 0.4.0-SNAPSHOT
+
+
+ 0.4.0-SNAPSHOT
+
+ 20160409062112
+
+