Messaging

Spring Cloud Contract 允许您验证使用消息传递作为通信方式的应用程序。本文档中显示的所有集成都适用于 Spring,但您也可以创建自己的集成并使用。

Spring Cloud Contract lets you verify applications that use messaging as a means of communication. All of the integrations shown in this document work with Spring, but you can also create one of your own and use that.

Messaging DSL Top-level Elements

消息传递的 DSL 看起来与专注于 HTTP 的 DSL 有点不同。以下部分解释了差异:

The DSL for messaging looks a little bit different than the one that focuses on HTTP. The following sections explain the differences:

Output Triggered by a Method

输出消息可以通过调用一个方法(例如,在启动合约和发送消息时调用的 Scheduler)来触发,如下例所示:

The output message can be triggered by calling a method (such as a Scheduler when a contract was started and when a message was sent), as shown in the following example:

Groovy
Unresolved directive in project-features-messaging.adoc - include::{tests_path}/samples-messaging-integration/src/test/groovy/com/example/IntegrationMessagingApplicationSpec.groovy[]
YAML
Unresolved directive in project-features-messaging.adoc - include::{verifier_root_path}/src/test/resources/yml/contract_message_method.yml[]

在前面的示例情况下,如果调用名为 bookReturnedTriggered 的方法,则输出消息将发送到 output。在消息发布者的方面,我们生成一个测试来调用该方法以触发消息。在消费者方面,可以使用 some_label 来触发消息。

In the previous example case, the output message is sent to output if a method called bookReturnedTriggered is invoked. On the message publisher’s side, we generate a test that calls that method to trigger the message. On the consumer side, you can use some_label to trigger the message.

Consumer/Producer

此部分仅对 Groovy DSL 有效。

This section is valid only for the Groovy DSL.

在 HTTP 中,您有 client/stub 和 `server/test 符号的概念。您还可以在消息传递中使用这些范例。此外,Spring Cloud Contract Verifier 还提供 consumerproducer 方法(请注意,您可以使用 $value 方法来提供 consumerproducer 部分)。

In HTTP, you have a notion of client/stub and `server/test notation. You can also use those paradigms in messaging. In addition, Spring Cloud Contract Verifier also provides the consumer and producer methods (note that you can use either $ or value methods to provide consumer and producer parts).

Common

inputoutputMessage 段中,你可以使用已在 base 类或静态导入中定义的 method 名称(例如,assertThatMessageIsOnTheQueue())来调用 assertThat。Spring Cloud Contract 在生成的测试中运行该方法。

In the input or outputMessage section, you can call assertThat with the name of a method (for example, assertThatMessageIsOnTheQueue()) that you have defined in the base class or in a static import. Spring Cloud Contract runs that method in the generated test.

Integrations

你可以使用以下集成配置之一:

You can use one of the following integration configurations:

  • Apache Camel

  • Spring Integration

  • Spring Cloud Stream

  • Spring JMS

由于我们使用 Spring Boot,所以如果你已将其中一个库添加到类路径,则会自动设置所有消息传递配置。

Since we use Spring Boot, if you have added one of these libraries to the classpath, all the messaging configuration is automatically set up.

请记住在生成测试的基本类上添加 @AutoConfigureMessageVerifier。否则,Spring Cloud Contract 的消息部分将无法正常工作。

Remember to put @AutoConfigureMessageVerifier on the base class of your generated tests. Otherwise, the messaging part of Spring Cloud Contract does not work.

如果你想使用 Spring Cloud Stream,请务必添加对 org.springframework.cloud:spring-cloud-stream 的测试依赖项,如下所示:

If you want to use Spring Cloud Stream, remember to add a test dependency on org.springframework.cloud:spring-cloud-stream, as follows:

Maven
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream</artifactId>
    <type>test-jar</type>
    <scope>test</scope>
    <classifier>test-binder</classifier>
</dependency>
Gradle
testImplementation(group: 'org.springframework.cloud', name: 'spring-cloud-stream', classifier: 'test-binder')

Manual Integration Testing

测试使用的主要接口是 org.springframework.cloud.contract.verifier.messaging.MessageVerifierSenderorg.springframework.cloud.contract.verifier.messaging.MessageVerifierReceiver。它定义如何发送和接收消息。

The main interface used by the tests is org.springframework.cloud.contract.verifier.messaging.MessageVerifierSender and org.springframework.cloud.contract.verifier.messaging.MessageVerifierReceiver. It defines how to send and receive messages.

在测试中,你可以注入 ContractVerifierMessageExchange 以发送和接收符合契约的消息。然后向测试添加 @AutoConfigureMessageVerifier。以下示例演示如何执行此操作:

In a test, you can inject a ContractVerifierMessageExchange to send and receive messages that follow the contract. Then add @AutoConfigureMessageVerifier to your test. The following example shows how to do so:

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

  @Autowired
  private MessageVerifier verifier;
  ...
}

如果您的测试也需要存根,则 @AutoConfigureStubRunner 包含了消息传递配置,因此您只需要一个注释。

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

Producer Side Messaging Test Generation

在 DSL 中具有 inputoutputMessage 段将导致在发布方一侧创建测试。默认情况下,会创建 JUnit 4 测试。但是,也可以创建 JUnit 5、TestNG 或 Spock 测试。

Having the input or outputMessage sections in your DSL results in creation of tests on the publisher’s side. By default, JUnit 4 tests are created. However, there is also a possibility to create JUnit 5, TestNG, or Spock tests.

传递给 messageFromsentTo 的目标对于不同的消息传递实现可能具有不同的含义。对于 Stream 和集成,它首先解析为 通道的 destination。然后,如果不存在 destination,则将其解析为一个通道名称。对于 Camel,那是一个特定组件(例如 jms)。

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

考虑以下契约:

Consider the following contract:

Groovy
Unresolved directive in project-features-messaging.adoc - include::{verifier_root_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[]
YAML
Unresolved directive in project-features-messaging.adoc - include::{verifier_root_path}/src/test/resources/yml/contract_message_scenario1.yml[]

对于前面的示例,将创建以下测试:

For the preceding example, the following test would be created:

JUnit
Unresolved directive in project-features-messaging.adoc - include::{verifier_root_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[]
Spock
Unresolved directive in project-features-messaging.adoc - include::{verifier_root_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[]

Consumer Stub Generation

与 HTTP 部分不同,在消息传递中,我们需要在 JAR 内发布契约定义,并附带存根。然后在消费者一侧解析它,并创建适当的存根路由。

Unlike in the HTTP part, in messaging, we need to publish the contract definition inside the JAR with a stub. Then it is parsed on the consumer side, and proper stubbed routes are created.

如果您的类路径上有多个框架,则 Stub Runner 需要定义应使用哪一个。假设您在类路径上有 AMQP、Spring Cloud Stream 和 Spring Integration,并且您要使用 Spring AMQP。然后您需要设置 stubrunner.stream.enabled=falsestubrunner.integration.enabled=false。以这种方式,唯一剩下的框架是 Spring AMQP。

If you have multiple frameworks on the classpath, Stub Runner needs to define which one should be used. Assume that you have AMQP, Spring Cloud Stream, and Spring Integration on the classpath and that you want to use Spring AMQP. Then you need to set stubrunner.stream.enabled=false and stubrunner.integration.enabled=false. That way, the only remaining framework is Spring AMQP.

Stub triggering

要触发消息,请使用 StubTrigger 接口,如下面的示例所示:

To trigger a message, use the StubTrigger interface, as the following example shows:

Unresolved directive in project-features-messaging.adoc - include::{stubrunner_core_path}/src/main/java/org/springframework/cloud/contract/stubrunner/StubTrigger.java[]

为方便起见,StubFinder 接口扩展了 StubTrigger,所以你只需在测试中使用其中之一。

For convenience, the StubFinder interface extends StubTrigger, so you need only one or the other in your tests.

StubTrigger 为你提供了以下触发消息的选项:

StubTrigger gives you the following options to trigger a message:

Trigger by Label

下面的示例演示如何使用标签触发消息:

The following example shows how to trigger a message with a label:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[]

Trigger by Group and Artifact IDs

下面的示例演示如何按组和制品 ID 触发消息:

The following example shows how to trigger a message by group and artifact IDs:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[]

Trigger by Artifact IDs

下面的示例演示如何从制品 ID 触发消息:

The following example shows how to trigger a message from artifact IDs:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[]

Trigger All Messages

下面的示例演示如何触发所有消息:

The following example shows how to trigger all messages:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[]

Consumer Side Messaging With Apache Camel

Spring Cloud Contract Stub Runner 的消息传递模块为你提供了一种与 Apache Camel 集成的简单方法。对于提供的制品,它会自动下载存根并注册所需的路由。

Spring Cloud Contract 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 Apache Camel to the Project

你可以在类路径上同时拥有 Apache Camel 和 Spring Cloud Contract Stub Runner。请务必用 @AutoConfigureStubRunner 为你的测试类添加注释。

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

如果你需要禁用此功能,请设置 stubrunner.camel.enabled=false 属性。

If you need to disable this functionality, set the stubrunner.camel.enabled=false property.

Examples

假设我们有以下 Maven 存储库,其中部署了 camelService 应用程序的存根:

Assume that we have the following Maven repository with deployed stubs for the camelService application:

└── .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:

├── META-INF
│   └── MANIFEST.MF
└── repository
    ├── accurest
    │   └── bookReturned1.groovy
    └── mappings

现在考虑以下契约:

Now consider the following contract:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/samples-messaging-camel/src/test/groovy/com/example/CamelMessagingApplicationSpec.groovy[]

为了从 return_book_1 标签触发消息,我们使用 StubTrigger 接口,如下所示:

To trigger a message from the return_book_1 label, we use the StubTrigger interface, as follows:

stubFinder.trigger("return_book_1")

这将向契约输出消息中描述的目标发送一条消息。

That will send out a message to the destination described in the output message of the contract.

Consumer Side Messaging with Spring Integration

Spring Cloud Contract Stub Runner 的消息传递模块提供了一种轻松的方式来与 Spring Integration 集成。对于提供的制品,它会自动下载存根并注册所需的路由。

Spring Cloud Contract Stub Runner’s messaging module gives you an easy way to integrate with Spring Integration. For the provided artifacts, it automatically downloads the stubs and registers the required routes.

Adding the Runner to the Project

你可以在类路径上同时拥有 Spring Integration 和 Spring Cloud Contract Stub Runner。别忘了使用 @AutoConfigureStubRunner 为你的测试类加注释。

You can have both Spring Integration and Spring Cloud Contract Stub Runner on the classpath. Remember to annotate your test class with @AutoConfigureStubRunner.

Disabling the Functionality

如果你需要禁用此功能,请设置 stubrunner.integration.enabled=false 属性。

If you need to disable this functionality, set the stubrunner.integration.enabled=false property.

Examples

假设我们有以下 Maven 存储库,其中部署了 integrationService 应用程序的存根:

Assume that you have the following Maven repository with deployed stubs for the integrationService application:

└── .m2
    └── repository
        └── io
            └── codearte
                └── accurest
                    └── stubs
                        └── integrationService
                            ├── 0.0.1-SNAPSHOT
                            │   ├── integrationService-0.0.1-SNAPSHOT.pom
                            │   ├── integrationService-0.0.1-SNAPSHOT-stubs.jar
                            │   └── maven-metadata-local.xml
                            └── maven-metadata-local.xml

此外,还要假设存根包含以下结构:

Further assume the stubs contain the following structure:

├── META-INF
│   └── MANIFEST.MF
└── repository
    ├── accurest
    │   └── bookReturned1.groovy
    └── mappings

考虑以下契约:

Consider the following contract:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-integration/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/integration/IntegrationStubRunnerSpec.groovy[]

现在考虑以下 Spring Integration 路由:

Now consider the following Spring Integration Route:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-integration/src/test/resources/integration-context.xml[]

为了从 return_book_1 标签触发消息,请使用 StubTrigger 接口,如下所示:

To trigger a message from the return_book_1 label, use the StubTrigger interface, as follows:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-integration/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/integration/IntegrationStubRunnerSpec.groovy[]

这将向契约输出消息中描述的目标发送一条消息。

That will send out a message to the destination described in the output message of the contract.

Consumer Side Messaging With Spring Cloud Stream

Spring Cloud Contract Stub Runner 的消息传递模块提供了一种轻松的方式来与 Spring Stream 集成。对于提供的制品,它会自动下载存根并注册所需的路由。

Spring Cloud Contract Stub Runner’s messaging module gives you an easy way to integrate with Spring Stream. For the provided artifacts, it automatically downloads the stubs and registers the required routes.

如果 Stub Runner 与 Stream messageFromsentTo 字符串的集成首先解析为 通道 destination,并且不存在此 destination,则目标解析为通道名称。

If Stub Runner’s integration with the Stream messageFrom or sentTo strings are resolved first as the destination of a channel and no such destination exists, the destination is resolved as a channel name.

如果你想要使用 Spring Cloud Stream,别忘了添加对 org.springframework.cloud:spring-cloud-stream 测试支持的依赖项,如下所示:

If you want to use Spring Cloud Stream, remember to add a dependency on org.springframework.cloud:spring-cloud-stream test support, as follows:

Maven
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-test-binder</artifactId>
    <scope>test</scope>
</dependency>
Gradle
testImplementation('org.springframework.cloud:spring-cloud-stream-test-binder')

Adding the Runner to the Project

你可以在类路径上同时拥有 Spring Cloud Stream 和 Spring Cloud Contract Stub Runner。别忘了使用 @AutoConfigureStubRunner 为你的测试类加注释。

You can have both Spring Cloud Stream and Spring Cloud Contract Stub Runner on the classpath. Remember to annotate your test class with @AutoConfigureStubRunner.

Disabling the Functionality

如果你需要禁用此功能,请设置 stubrunner.stream.enabled=false 属性。

If you need to disable this functionality, set the stubrunner.stream.enabled=false property.

Examples

假设我们有以下 Maven 存储库,其中部署了 streamService 应用程序的存根:

Assume that you have the following Maven repository with deployed stubs for the streamService application:

└── .m2
    └── repository
        └── io
            └── codearte
                └── accurest
                    └── stubs
                        └── streamService
                            ├── 0.0.1-SNAPSHOT
                            │   ├── streamService-0.0.1-SNAPSHOT.pom
                            │   ├── streamService-0.0.1-SNAPSHOT-stubs.jar
                            │   └── maven-metadata-local.xml
                            └── maven-metadata-local.xml

此外,还要假设存根包含以下结构:

Further assume the stubs contain the following structure:

├── META-INF
│   └── MANIFEST.MF
└── repository
    ├── accurest
    │   └── bookReturned1.groovy
    └── mappings

考虑以下契约:

Consider the following contract:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[]

现在考虑以下 Spring Cloud Stream 函数配置:

Now consider the following Spring Cloud Stream function configuration:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[]

现在考虑以下 Spring 配置:

Now consider the following Spring configuration:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/resources/application.yml[]

为了从 return_book_1 标签触发消息,请使用 StubTrigger 接口,如下所示:

To trigger a message from the return_book_1 label, use the StubTrigger interface as follows:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[]

这将向契约输出消息中描述的目标发送一条消息。

That will send out a message to the destination described in the output message of the contract.

Consumer Side Messaging With Spring JMS

Spring Cloud Contract Stub Runner 的消息模块提供了一种轻松集成 Spring JMS 的方法。

Spring Cloud Contract Stub Runner’s messaging module provides an easy way to integrate with Spring JMS.

集成要求您运行 JMS 代理实例。

The integration assumes that you have a running instance of a JMS broker.

Adding the Runner to the Project

您需要同时将 Spring JMS 和 Spring Cloud Contract Stub Runner 放入类路径。请务必使用 @AutoConfigureStubRunner 为您的测试类添加注解。

You need to have both Spring JMS and Spring Cloud Contract Stub Runner on the classpath. Remember to annotate your test class with @AutoConfigureStubRunner.

Examples

假设存根结构如下所示:

Assume that the stub structure looks as follows:

├── stubs
    └── bookReturned1.groovy

此外,假设有以下测试配置:

Further assume the following test configuration:

stubrunner:
  repository-root: stubs:classpath:/stubs/
  ids: my:stubs
  stubs-mode: remote
spring:
  activemq:
    send-timeout: 1000
  jms:
    template:
      receive-timeout: 1000

现在考虑以下契约:

Now consider the following contract:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-jms/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/jms/JmsStubRunnerSpec.groovy[]

为了从 return_book_1 标签触发消息,我们使用 StubTrigger 接口,如下所示:

To trigger a message from the return_book_1 label, we use the StubTrigger interface, as follows:

Unresolved directive in project-features-messaging.adoc - include::{tests_path}/spring-cloud-contract-stub-runner-jms/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/jms/JmsStubRunnerSpec.groovy[]

这将向契约输出消息中描述的目标发送一条消息。

That will send out a message to the destination described in the output message of the contract.