4. Spring Cloud Contract Verifier Messaging
Prev |  | Next

# 4. Spring Cloud Contract Verifier Messaging

Spring Cloud Contract Verifier allows you to verify your application that uses messaging as means of communication. All of our integrations are working with Spring but you can also create one yourself and use it.

## 4.1 Integrations

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.

| Important
Remember to put `@AutoConfigureMessageVerifier` on the base class of your generated tests. Otherwise messaging part of Spring Cloud Contract Verifier will not work.

| Important
If you want to use Spring Cloud Stream remember to add a `org.springframework.cloud:spring-cloud-stream-test-support` dependency.

Maven.

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-stream-test-support</artifactId>
        <scope>test</scope>
    </dependency>

Gradle.

    testCompile "org.springframework.cloud:spring-cloud-stream-test-support"

## 4.2 Manual Integration Testing

The main interface used by the tests is the `org.springframework.cloud.contract.verifier.messaging.MessageVerifier`. It defines how to send and receive messages. You can create your own implementation to achieve the same goal.

In the a test you can inject a `ContractVerifierMessageExchange` to send and receive messages that follow the contract. Then add `@AutoConfigureMessageVerifier` to your test, e.g.

    @RunWith(SpringTestRunner.class)
    @SpringBootTest
    @AutoConfigureMessageVerifier
    public static class MessagingContractTests {

      @Autowired
      private MessageVerifier verifier;
      ...
    }

| Note
If your tests require stubs as well, then `@AutoConfigureStubRunner` includes the messaging configuration, so you only need the one annotation.

## 4.3 Publisher side test generation

Having the `input` or `outputMessage` sections in your DSL will result in creation of tests on the publisher’s side. By default JUnit tests will be created, however there is also a possibility to create Spock tests.

There are 3 main scenarios that we should take into consideration:

- Scenario 1: there is no input message that produces an output one. The output message is triggered by a component inside the application (e.g. scheduler)
- Scenario 2: the input message triggers an output message
- Scenario 3: the input message is consumed and there is no output message

| Important
The destination passed to `messageFrom` or `sentTo` can have different meanings for different messaging implementations. For Stream and Integration it’s first resolved as a `destination` of a channel, and then if there is no such `destination` it’s resolved as a channel name. For Camel that’s a certain component (e.x. `jms`).

Example for Camel:

### 4.3.1 Scenario 1 (no input message)

For the given contract:

    def contractDsl = Contract.make {
    	label 'some_label'
    	input {
    		triggeredBy('bookReturnedTriggered()')
    	}
    	outputMessage {
    		sentTo('activemq:output')
    		body('''{ "bookName" : "foo" }''')
    		headers {
    			header('BOOK-NAME', 'foo')
    			messagingContentType(applicationJson())
    		}
    	}
    }

The following JUnit test will be created:

    '''
     // when:
      bookReturnedTriggered();

     // then:
      ContractVerifierMessage response = contractVerifierMessaging.receive("activemq:output");
      assertThat(response).isNotNull();
      assertThat(response.getHeader("BOOK-NAME")).isNotNull();
      assertThat(response.getHeader("BOOK-NAME").toString()).isEqualTo("foo");
      assertThat(response.getHeader("contentType")).isNotNull();
      assertThat(response.getHeader("contentType").toString()).isEqualTo("application/json");
     // and:
      DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
      assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
    '''

And the following Spock test would be created:

    '''
     when:
      bookReturnedTriggered()

     then:
      ContractVerifierMessage response = contractVerifierMessaging.receive('activemq:output')
      assert response != null
      response.getHeader('BOOK-NAME')?.toString()  == 'foo'
      response.getHeader('contentType')?.toString()  == 'application/json'
     and:
      DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
      assertThatJson(parsedJson).field("bookName").isEqualTo("foo")

    '''

### 4.3.2 Scenario 2 (output triggered by input)

For the given contract:

    def contractDsl = 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')
    		}
    	}
    }

The following JUnit test will be created:

    '''
    // given:
     ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
      "{\\"bookName\\":\\"foo\\"}"
    , headers()
      .header("sample", "header"));

    // when:
     contractVerifierMessaging.send(inputMessage, "jms:input");

    // then:
     ContractVerifierMessage response = contractVerifierMessaging.receive("jms:output");
     assertThat(response).isNotNull();
     assertThat(response.getHeader("BOOK-NAME")).isNotNull();
     assertThat(response.getHeader("BOOK-NAME").toString()).isEqualTo("foo");
    // and:
     DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
     assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
    '''

And the following Spock test would be created:

    """\
    given:
       ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
        '''{"bookName":"foo"}''',
        ['sample': 'header']
      )

    when:
       contractVerifierMessaging.send(inputMessage, 'jms:input')

    then:
       ContractVerifierMessage response = contractVerifierMessaging.receive('jms:output')
       assert response !- null
       response.getHeader('BOOK-NAME')?.toString()  == 'foo'
    and:
       DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
       assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
    """

### 4.3.3 Scenario 3 (no output message)

For the given contract:

    def contractDsl = Contract.make {
    	label 'some_label'
    	input {
    		messageFrom('jms:delete')
    		messageBody([
    				bookName: 'foo'
    		])
    		messageHeaders {
    			header('sample', 'header')
    		}
    		assertThat('bookWasDeleted()')
    	}
    }

The following JUnit test will be created:

    '''
    // given:
     ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
    	"{\\"bookName\\":\\"foo\\"}"
    , headers()
    	.header("sample", "header"));

    // when:
     contractVerifierMessaging.send(inputMessage, "jms:delete");

    // then:
     bookWasDeleted();
    '''

And the following Spock test would be created:

    '''
    given:
    	 ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
    		\'\'\'{"bookName":"foo"}\'\'\',
    		['sample': 'header']
    	)

    when:
    	 contractVerifierMessaging.send(inputMessage, 'jms:delete')

    then:
    	 noExceptionThrown()
    	 bookWasDeleted()
    '''

## 4.4 Consumer Stub Side generation

Unlike the HTTP part - in Messaging we need to publish the Groovy DSL inside the JAR with a stub. Then it’s parsed on the consumer side and proper stubbed routes are created.

For more information please consult the Stub Runner Messaging sections.

Maven.

    <dependencies>
    	<dependency>
    		<groupId>org.springframework.cloud</groupId>
    		<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    	</dependency>

    	<dependency>
    		<groupId>org.springframework.cloud</groupId>
    		<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
    		<scope>test</scope>
    	</dependency>
    	<dependency>
    		<groupId>org.springframework.cloud</groupId>
    		<artifactId>spring-cloud-stream-test-support</artifactId>
    		<scope>test</scope>
    	</dependency>
    </dependencies>

    <dependencyManagement>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-dependencies</artifactId>
    			<version>Dalston.BUILD-SNAPSHOT</version>
    			<type>pom</type>
    			<scope>import</scope>
    		</dependency>
    	</dependencies>
    </dependencyManagement>

Gradle.

    ext {
    	contractsDir = file("mappings")
    	stubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
    }

    // Automatically added by plugin:
    // copyContracts - copies contracts to the output folder from which JAR will be created
    // verifierStubsJar - JAR with a provided stub suffix
    // the presented publication is also added by the plugin but you can modify it as you wish

    publishing {
    	publications {
    		stubs(MavenPublication) {
    			artifactId "${project.name}-stubs"
    			artifact verifierStubsJar
    		}
    	}
    }

Prev |  | Next
3. Spring Cloud Contract Verifier Setup | Home | 5. Spring Cloud Contract Stub Runner