该版本仍在开发中,尚未被视为稳定。对于最新的稳定版本,请使用 spring-cloud-contract 5.0.0!spring-doc.cadn.net.cn

Docker 项目

在本节中,我们发布了Springcloud/Spring-Cloud-ContractDocker 镜像 其中包含一个生成测试并运行测试的项目明确模式 对抗正在运行的应用程序。spring-doc.cadn.net.cn

明确模式意味着由合同生成的测试发送 是真实的请求,而不是嘲笑的请求。

我们还出版了春云/春云合同存根跑者Docker 镜像 这也开启了《Stub Runner》的独立版本。spring-doc.cadn.net.cn

Maven、JARs和二进制存储简要介绍

由于非JVM项目可以使用Docker镜像,因此 请解释Spring Cloud合约打包默认值背后的基本术语。spring-doc.cadn.net.cn

以下部分定义摘自Maven词汇表spring-doc.cadn.net.cn

  • 项目Maven 以项目为思维方式。项目 你只能建造。这些项目遵循明确定义的 “项目对象模型”。项目可以依赖其他项目——在这种情况下,依赖关系被称为“依赖关系”。项目可能 与多个子项目保持一致。然而,这些子项目仍然是 被平等地当作项目对待。spring-doc.cadn.net.cn

  • 人工制品:人工物是指被生产或使用的物品 被一个项目。Maven为某个项目制作的文物示例 包括JAR文件以及源代码和二进制发行版。每件文物 由一个组ID和一个工件ID唯一标识,该ID为 在群体中独一无二。spring-doc.cadn.net.cn

  • : JAR代表Java Archive。其节目形式基于以下内容 ZIP文件格式。Spring Cloud Contract 打包了合同并生成 JAR文件中的存根。spring-doc.cadn.net.cn

  • 群组ID: 组ID是项目的通用唯一标识符。 虽然这通常只是项目名称(例如,共享收藏), 使用完全限定的包名称来区分它很有帮助 来自其他同名项目(例如,org.apache.maven). 通常,当发布到工件管理器时,群组ID得到 斜杠分隔,构成URL的一部分。例如,对于组IDcom.example以及一个伪影ID应用,结果为/com/example/application/.spring-doc.cadn.net.cn

  • 分类:Maven 依赖符号如下:groupId:artifactId:version:classifier.分类词是一个附加后缀 传递给依赖——例如,存根来源.同样的依赖关系 (例如,com.example:应用)可以产生多个伪影,使得 与分类器相差。spring-doc.cadn.net.cn

  • 工件管理器: 当你生成二进制文件、源代码或包时,你会 希望这些内容能供他人下载、参考或重用。在 JVM世界中,这些文物通常是JAR。对Ruby来说,那些神器是宝石。 对于 Docker 来说,这些工件就是 Docker 镜像。你可以把那些文物保存起来 在经理身上。此类管理器的例子包括ArtifactoryNexusspring-doc.cadn.net.cn

生成生产方测试

图片搜索合同/合同文件夹。 运行测试的输出可以在/spring-cloud-contract/build文件夹(用于调试) 目的)。spring-doc.cadn.net.cn

你可以挂载你的合同并传递环境变量。 画面如下:spring-doc.cadn.net.cn

环境变量

Docker 镜像需要指向一些环境变量 你的正在运行的应用程序,连接到工件管理器实例,依此类推。 以下列表描述了环境变量:spring-doc.cadn.net.cn

表1。Docker 环境变量

名称spring-doc.cadn.net.cn

描述spring-doc.cadn.net.cn

默认值spring-doc.cadn.net.cn

ADDITIONAL_FLAGSspring-doc.cadn.net.cn

(仅限 Docker 镜像)Gradle构建将获得更多旗帜spring-doc.cadn.net.cn

调试spring-doc.cadn.net.cn

(仅限 Docker 镜像)适用于 Docker 镜像——开启 Gradle 构建的调试模式spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_ARTIFACT_IDspring-doc.cadn.net.cn

项目工件识别及合同spring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_CLASSIFIERspring-doc.cadn.net.cn

项目与合同的分类spring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_GROUP_IDspring-doc.cadn.net.cn

项目组别与合同spring-doc.cadn.net.cn

com.examplespring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_PATHspring-doc.cadn.net.cn

项目内部的合同路径。默认为斜杠分离EXTERNAL_CONTRACTS_GROUP_ID与 和 连接/EXTERNAL_CONTRACTS_ARTIFACT_ID。例如 对于组ID 'cat-server-side.dog以及工件ID,将得到猫/狗/鱼对于契约路径。spring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_PASSWORDspring-doc.cadn.net.cn

(可选)密码如果EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL需要认证。默认是“REPO_WITH_BINARIES_PASSWORD,如果没设置,则默认为”密码”spring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URLspring-doc.cadn.net.cn

你的工件管理器网址。它默认为REPO_WITH_BINARIES_URL环境变量,如果未设置,默认为localhost:8081/artifactory/libs-release-localspring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_USERNAMEspring-doc.cadn.net.cn

(可选)用户名如果是EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL需要认证。它默认为REPO_WITH_BINARIES_USERNAME.如果没有设置,默认会变成“admin”spring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_VERSIONspring-doc.cadn.net.cn

项目的合同版本。废弃相当于选择最新的spring-doc.cadn.net.cn

+spring-doc.cadn.net.cn

EXTERNAL_CONTRACTS_WORK_OFFLINEspring-doc.cadn.net.cn

如果设置为true,从容器中取回带有合同的神器.m2.安装你的本地.m2作为集装箱可获得的容量/root/.m2路径spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

FAIL_ON_NO_CONTRACTSspring-doc.cadn.net.cn

如果没有合同,构建应该失败吗?spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

MESSAGING_TYPEspring-doc.cadn.net.cn

信息类型。可以是[兔子]或[卡夫卡]。spring-doc.cadn.net.cn

PRODUCER_STUBS_CLASSIFIERspring-doc.cadn.net.cn

用于生成生产者小作品的归档分类器spring-doc.cadn.net.cn

存根spring-doc.cadn.net.cn

PROJECT_GROUPspring-doc.cadn.net.cn

你的项目组IDspring-doc.cadn.net.cn

com.examplespring-doc.cadn.net.cn

PROJECT_NAMEspring-doc.cadn.net.cn

你项目的工件IDspring-doc.cadn.net.cn

示例spring-doc.cadn.net.cn

PROJECT_VERSIONspring-doc.cadn.net.cn

你项目的版本spring-doc.cadn.net.cn

0.0.1-快照spring-doc.cadn.net.cn

PUBLISH_ARTIFACTSspring-doc.cadn.net.cn

如果设置为true将文件发布到二进制存储spring-doc.cadn.net.cn

truespring-doc.cadn.net.cn

PUBLISH_ARTIFACTS_OFFLINEspring-doc.cadn.net.cn

如果设置为true,将文物发布到本地M2spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

PUBLISH_STUBS_TO_SCMspring-doc.cadn.net.cn

如果设置为true将执行将stubs发布到SCM的任务spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

REPO_ALLOW_INSECURE_PROTOCOLspring-doc.cadn.net.cn

(可选)如果<true>,允许通过不安全的HTTP向Artifact Manager发布工件spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

REPO_WITH_BINARIES_PASSWORDspring-doc.cadn.net.cn

(可选)当文物管理器被保护时,密码spring-doc.cadn.net.cn

密码spring-doc.cadn.net.cn

REPO_WITH_BINARIES_URLspring-doc.cadn.net.cn

你的工件管理器的网址(本地运行时默认为Artifactory的默认URL)spring-doc.cadn.net.cn

localhost:8081/artifactory/libs-release-localspring-doc.cadn.net.cn

REPO_WITH_BINARIES_USERNAMEspring-doc.cadn.net.cn

(可选)当工件管理器被保护时的用户名spring-doc.cadn.net.cn

管理spring-doc.cadn.net.cn

STANDALONE_PROTOCOLspring-doc.cadn.net.cn

对于独立版本,应该添加哪个额外协议spring-doc.cadn.net.cn

测试时使用以下环境变量:spring-doc.cadn.net.cn

表2。Docker 环境变量 - 运行时读取

名称spring-doc.cadn.net.cn

描述spring-doc.cadn.net.cn

默认值spring-doc.cadn.net.cn

APPLICATION_BASE_URLspring-doc.cadn.net.cn

应用程序运行的URL。spring-doc.cadn.net.cn

APPLICATION_PASSWORDspring-doc.cadn.net.cn

访问应用需使用可选密码。spring-doc.cadn.net.cn

APPLICATION_USERNAMEspring-doc.cadn.net.cn

访问应用时需使用可选用户名。spring-doc.cadn.net.cn

MESSAGING_TRIGGER_CONNECT_TIMEOUTspring-doc.cadn.net.cn

超时连接应用程序以触发消息。spring-doc.cadn.net.cn

5000spring-doc.cadn.net.cn

MESSAGING_TRIGGER_READ_TIMEOUTspring-doc.cadn.net.cn

超时以读取应用程序的响应以触发消息。spring-doc.cadn.net.cn

5000spring-doc.cadn.net.cn

MESSAGING_TYPEspring-doc.cadn.net.cn

信息类型。可以是[兔子]或[卡夫卡]。spring-doc.cadn.net.cn

MESSAGING_TYPEspring-doc.cadn.net.cn

定义了处理基于消息的合同时的消息类型。spring-doc.cadn.net.cn

SPRING_KAFKA_BOOTSTRAP_SERVERSspring-doc.cadn.net.cn

对于卡夫卡来说——中介地址。spring-doc.cadn.net.cn

SPRING_RABBITMQ_ADDRESSESspring-doc.cadn.net.cn

对于RabbitMQ——经纪人地址。spring-doc.cadn.net.cn

定制gradle构建

你可以提供定制化方案gradle.build在运行容器时,通过挂载你自定义的构建文件作为卷来在容器中运行:spring-doc.cadn.net.cn

$ docker run -v <absolute-path-of-your-custom-file>:/spring-cloud-contract/build.gradle springcloud/spring-cloud-contract:<version>

通过HTTP的使用示例

本节我们将探讨一个简单的MVC应用。开始时,克隆以下内容 通过执行以下命令,将git仓库和CD迁移到最终目录:spring-doc.cadn.net.cn

$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
$ cd bookstore

合同可在/合同文件夹。spring-doc.cadn.net.cn

既然我们想运行测试,可以执行以下命令:spring-doc.cadn.net.cn

$ npm test

不过,为了学习目的,我们把它拆分成如下几个部分:spring-doc.cadn.net.cn

# Stop docker infra (nodejs, artifactory)
$ ./stop_infra.sh
# Start docker infra (nodejs, artifactory)
$ ./setup_infra.sh

# Kill & Run app
$ pkill -f "node app"
$ nohup node app &

# Prepare environment variables
$ SC_CONTRACT_DOCKER_VERSION="..."
$ APP_IP="192.168.0.100"
$ APP_PORT="3000"
$ ARTIFACTORY_PORT="8081"
$ APPLICATION_BASE_URL="http://${APP_IP}:${APP_PORT}"
$ ARTIFACTORY_URL="http://${APP_IP}:${ARTIFACTORY_PORT}/artifactory/libs-release-local"
$ CURRENT_DIR="$( pwd )"
$ CURRENT_FOLDER_NAME=${PWD##*/}
$ PROJECT_VERSION="0.0.1.RELEASE"

# Run contract tests
$ docker run  --rm -e "APPLICATION_BASE_URL=${APPLICATION_BASE_URL}" -e "PUBLISH_ARTIFACTS=true" -e "PROJECT_NAME=${CURRENT_FOLDER_NAME}" -e "REPO_WITH_BINARIES_URL=${ARTIFACTORY_URL}" -e "PROJECT_VERSION=${PROJECT_VERSION}" -v "${CURRENT_DIR}/contracts/:/contracts:ro" -v "${CURRENT_DIR}/node_modules/spring-cloud-contract/output:/spring-cloud-contract-output/" springcloud/spring-cloud-contract:"${SC_CONTRACT_DOCKER_VERSION}"

# Kill app
$ pkill -f "node app"

通过bash脚本,会发生以下情况:spring-doc.cadn.net.cn

通过消息传递的使用示例

如果你想通过 Docker 镜像(例如 Clip Agent)使用Spring Cloud Contract来进行消息传递(例如 如果申请多语种),那么你需要满足以下前提条件:spring-doc.cadn.net.cn

消息合约示例

合同需要调用triggerMessage(...)方法。该方法已经在 docker 镜像中所有测试的基础类中提供,并会向生产方的 HTTP 端点发送请求。下面你可以找到这类合同的示例。spring-doc.cadn.net.cn

槽的
import org.springframework.cloud.contract.spec.Contract

Contract.make {
    description 'Send a pong message in response to a ping message'
    label 'ping_pong'
    input {
        // You have to provide the `triggerMessage` method with the `label`
        // as a String parameter of the method
        triggeredBy('triggerMessage("ping_pong")')
    }
    outputMessage {
        sentTo('output')
        body([
            message: 'pong'
        ])
    }
    metadata(
        [amqp:
         [
           outputMessage: [
               connectToBroker: [
                   declareQueueWithName: "queue"
               ],
                messageProperties: [
                    receivedRoutingKey: '#'
                ]
           ]
         ]
        ])
}
YAML
description: 'Send a pong message in response to a ping message'
label: 'ping_pong'
input:
    # You have to provide the `triggerMessage` method with the `label`
    # as a String parameter of the method
    triggeredBy: 'triggerMessage("ping_pong")'
outputMessage:
    sentTo: 'output'
    body:
        message: 'pong'
metadata:
    amqp:
        outputMessage:
            connectToBroker:
                declareQueueWithName: "queue"
            messageProperties:
                receivedRoutingKey: '#'

HTTP 端点用于触发消息

为什么需要开发这样的终点?春云合约 需要用多种语言生成代码(就像在 Java 中一样),才能实现生产触发 向经纪人发送消息的代码。如果没有生成这样的代码,我们仍然需要能够触发消息,而实现这一点的方法是提供一个HTTP端点,用户会用他们选择的语言准备。spring-doc.cadn.net.cn

端点必须具有以下配置:spring-doc.cadn.net.cn

下面你有一个这样的端点示例。如果你感兴趣 用你的语言举例,不要犹豫提交问题 Github上的Spring Cloud Contract仓库spring-doc.cadn.net.cn

Python
#!/usr/bin/env python

from flask import Flask
from flask import jsonify
import pika
import os

app = Flask(__name__)

# Production code that sends a message to RabbitMQ
def send_message(cmd):
    connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()
    channel.basic_publish(
        exchange='output',
        routing_key='#',
        body=cmd,
        properties=pika.BasicProperties(
            delivery_mode=2,  # make message persistent
        ))
    connection.close()
    return " [x] Sent via Rabbit: %s" % cmd

# This should be ran in tests (shouldn't be publicly available)
if 'CONTRACT_TEST' in os.environ:
    @app.route('/springcloudcontract/<label>', methods=['POST'])
    def springcloudcontract(label):
        if label == "ping_pong":
            return send_message('{"message":"pong"}')
        else:
            raise ValueError('No such label expected.')

在生产者端运行消息测试

现在,让我们从合同中生成测试,以测试生产方。 我们将运行bash代码启动Docker镜像 不过,对于附加的合约,我们还会添加消息传递的变量 代码工作。在这种情况下,假设合同存储在 一个Git仓库。spring-doc.cadn.net.cn

#!/bin/bash
set -x

CURRENT_DIR="$( pwd )"

export SC_CONTRACT_DOCKER_VERSION="${SC_CONTRACT_DOCKER_VERSION:-4.0.1-SNAPSHOT}"
export APP_IP="$( ./whats_my_ip.sh )"
export APP_PORT="${APP_PORT:-8000}"
export APPLICATION_BASE_URL="http://${APP_IP}:${APP_PORT}"
export PROJECT_GROUP="${PROJECT_GROUP:-group}"
export PROJECT_NAME="${PROJECT_NAME:-application}"
export PROJECT_VERSION="${PROJECT_VERSION:-0.0.1-SNAPSHOT}"
export PRODUCER_STUBS_CLASSIFIER="${PRODUCER_STUBS_CLASSIFIER:-stubs}"
export FAIL_ON_NO_CONTRACTS="${FAIL_ON_NO_CONTRACTS:-false}"
# In our Python app we want to enable the HTTP endpoint
export CONTRACT_TEST="true"
# In the Verifier docker container we want to add support for RabbitMQ
export MESSAGING_TYPE="rabbit"

# Let's start the infrastructure (e.g. via Docker Compose)
yes | docker-compose kill || echo "Nothing running"
docker-compose up -d

echo "SC Contract Version [${SC_CONTRACT_DOCKER_VERSION}]"
echo "Application URL [${APPLICATION_BASE_URL}]"
echo "Project Version [${PROJECT_VERSION}]"

# Let's run python app
gunicorn -w 4 --bind 0.0.0.0 main:app &
APP_PID=$!

# Generate and run tests
docker run  --rm \
                --name verifier \
                # For the image to find the RabbitMQ running in another container
                -e "SPRING_RABBITMQ_ADDRESSES=${APP_IP}:5672" \
                # We need to tell the container what messaging middleware we will use
                -e "MESSAGING_TYPE=${MESSAGING_TYPE}" \
                -e "PUBLISH_STUBS_TO_SCM=false" \
                -e "PUBLISH_ARTIFACTS=false" \
                -e "APPLICATION_BASE_URL=${APPLICATION_BASE_URL}" \
                -e "PROJECT_NAME=${PROJECT_NAME}" \
                -e "PROJECT_GROUP=${PROJECT_GROUP}" \
                -e "PROJECT_VERSION=${PROJECT_VERSION}" \
                -e "EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL=git://https://github.com/marcingrzejszczak/cdct_python_contracts.git" \
                -e "EXTERNAL_CONTRACTS_ARTIFACT_ID=${PROJECT_NAME}" \
                -e "EXTERNAL_CONTRACTS_GROUP_ID=${PROJECT_GROUP}" \
                -e "EXTERNAL_CONTRACTS_VERSION=${PROJECT_VERSION}" \
                -v "${CURRENT_DIR}/build/spring-cloud-contract/output:/spring-cloud-contract-output/" \
                springcloud/spring-cloud-contract:"${SC_CONTRACT_DOCKER_VERSION}"

kill $APP_PID

yes | docker-compose kill

结果如下:spring-doc.cadn.net.cn

  • 测试将根据从 Git 获取的合同生成spring-doc.cadn.net.cn

  • 合同中我们提供了一个元数据条目,称为声明QueueWithName(队列名)这会导致在发送消息请求前,RabbitMQ 中创建一个带有该名称的队列spring-doc.cadn.net.cn

  • 通过triggerMessage(“ping_pong”)方法调用 POST 请求到 Python 应用程序/春云合约/ping_pong终点将被确定spring-doc.cadn.net.cn

  • Python 应用程序会生成并发送'{“信息”:“pong”}'通过RabbitMQ的JSON传输到一个名为输出spring-doc.cadn.net.cn

  • 生成的测试将轮询发送给输出交换spring-doc.cadn.net.cn

  • 消息一旦收到,就会声明其内容spring-doc.cadn.net.cn

测试通过后,我们知道消息是正确从Python应用发送给RabbitMQ的。spring-doc.cadn.net.cn

在消费者端运行存根

本节介绍如何在消费者端使用 Docker 获取和运行存根。spring-doc.cadn.net.cn

我们发布春云/春云合同存根跑者Docker 镜像 这也开启了《Stub Runner》的独立版本。spring-doc.cadn.net.cn

安全

由于 Spring Cloud Contract Stub Runner Docker 镜像使用了独立版本的 Stub Runner,因此需要采取相同的安全考虑。你可以在文档的这一部分阅读更多相关内容。spring-doc.cadn.net.cn

环境变量

你可以运行 Docker 镜像,并将 JUnit 和 Spring 的常见属性作为环境变量传递。惯例是所有 字母应该用大写字母。 点(.)应被下划线()字符替换。例如 这_spring.cloud.contract.stubrunner.repositoryRoot(Root)财产应当被代表 作为SPRING_COUD_CONTRACT_STUBRUNNER_REPOSITORY_ROOT环境变量。spring-doc.cadn.net.cn

除了这些变量外,你还可以设置以下几个:spring-doc.cadn.net.cn

使用示例

我们想使用在这个[docker-server-side]步骤中创建的stubs。 假设我们想在端口上运行存根9876.你可以看到NodeJS的代码 通过克隆仓库并更改到以下命令中指定的目录:spring-doc.cadn.net.cn

$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
$ cd bookstore

现在我们可以用存根运行 Stub Runner Boot 应用程序,方法是运行以下作 命令:spring-doc.cadn.net.cn

# Provide the Spring Cloud Contract Docker version
$ SC_CONTRACT_DOCKER_VERSION="..."
# The IP at which the app is running and Docker container can reach it
$ APP_IP="192.168.0.100"
# Spring Cloud Contract Stub Runner properties
$ SPRING_CLOUD_CONTRACT_STUBRUNNER_PORT="8083"
# Stub coordinates 'groupId:artifactId:version:classifier:port'
$ SPRING_CLOUD_CONTRACT_STUBRUNNER_IDS="com.example:bookstore:0.0.1.RELEASE:stubs:9876"
$ SPRING_CLOUD_CONTRACT_STUBRUNNER_REPOSITORY_ROOT="http://${APP_IP}:8081/artifactory/libs-release-local"
# Run the docker with Stub Runner Boot
$ docker run  --rm \
    -e "SPRING_CLOUD_CONTRACT_STUBRUNNER_IDS=${STUBRUNNER_IDS}" \
    -e "SPRING_CLOUD_CONTRACT_STUBRUNNER_REPOSITORY_ROOT=${STUBRUNNER_REPOSITORY_ROOT}" \
    -e "SPRING_CLOUD_CONTRACT_STUBRUNNER_STUBS_MODE=REMOTE" \
    -p "${STUBRUNNER_PORT}:${STUBRUNNER_PORT}" \
    -p "9876:9876" \
    springcloud/spring-cloud-contract-stub-runner:"${SC_CONTRACT_DOCKER_VERSION}"

当上述命令执行时,spring-doc.cadn.net.cn

在服务器端,我们构建了一个有状态的存根。我们可以用卷曲来断言 要确保存根设置得当。为此,运行以下命令:spring-doc.cadn.net.cn

# let's run the first request (no response is returned)
$ curl -H "Content-Type:application/json" -X POST --data '{ "title" : "Title", "genre" : "Genre", "description" : "Description", "author" : "Author", "publisher" : "Publisher", "pages" : 100, "image_url" : "https://d213dhlpdb53mu.cloudfront.net/assets/pivotal-square-logo-41418bd391196c3022f3cd9f3959b3f6d7764c47873d858583384e759c7db435.svg", "buy_url" : "https://pivotal.io" }' http://localhost:9876/api/books
# Now time for the second request
$ curl -X GET http://localhost:9876/api/books
# You will receive contents of the JSON
如果你想在主机上使用你本地搭建的存根, 你应该设置-e STUBRUNNER_STUBS_MODE=局部环境变量与挂载 你本地M2的体积(-v “${HOME}/.m2/:/home/scc/.m2:rw”).

消息应用示例

为了让消息传递正常,只需通过MESSAGING_TYPE环境变量卡 夫 卡值。这将引出设置 Stub Runner 启动 Docker 镜像,带有连接经纪者所需的依赖。spring-doc.cadn.net.cn

为了设置连接属性,你可以查看 Spring Cloud Stream 属性页面,设置合适的环境变量。spring-doc.cadn.net.cn

最常见的属性是运行中的中部(midwara)的位置。 如果要设置一个属性,则称为spring.rabbitmq.addressesspring.kafka.bootstrap-servers然后你应该给环境变量命名SPRING_RABBITMQ_ADDRESSESSPRING_KAFKA_BOOTSTRAP_SERVERS分别。spring-doc.cadn.net.cn

针对现有中间件运行合同测试

有正当理由对现有中间件进行合同测试。一些 测试框架可能会给你误报结果——即你构建中的测试 通过,而生产时通信失败。spring-doc.cadn.net.cn

在 Spring Cloud Contract 的 Docker 镜像中,我们提供了连接现有中间件的选项。 如前述小节所述,我们开箱即用支持 Kafka 和 RabbitMQ。然而 通过Apache Camel组件,我们支持。 其他中间件也是如此。让我们看看以下的使用示例。spring-doc.cadn.net.cn

Spring Cloud Contract Docker 与运行中间件

为了连接任意中间件,我们将利用独立作品元数据条目 在合同部分。spring-doc.cadn.net.cn

description: 'Send a pong message in response to a ping message'
label: 'standalone_ping_pong' (1)
input:
  triggeredBy: 'triggerMessage("ping_pong")' (2)
outputMessage:
  sentTo: 'rabbitmq:output' (3)
  body: (4)
    message: 'pong'
metadata:
  standalone: (5)
    setup: (6)
      options: rabbitmq:output?queue=output&routingKey=(7)
    outputMessage: (8)
      additionalOptions: routingKey=#&queue=output (9)
1 标签,我们可以通过Stub Runner触发消息
2 和之前的消息示例一样,我们需要触发运行应用中的HTTP端点,使其按照提供的协议发送消息
3 协议:目的地应阿帕奇骆驼的要求
4 输出消息体
5 独立元数据条目
6 设置部分将包含如何在实际调用应用的HTTP端点之前准备执行合同测试的信息
7 Apache Camel URI 将在设置阶段调用。在这种情况下,我们将尝试在输出交换,并且由于拥有队列=输出路由键=一个带名称的队列输出将被设置为并绑定于输出与路由密钥的交换
8 附加的选项(更技术性的内容)将附加于协议:目的地从点(3)起——将合并成以下格式rabbitmq:output?routingKey=#&queue=output.

为了通过合同测试,我们需要像往常一样,在多语种环境中进行消息传递 一个正在运行的应用程序和运行中的中间件。这次我们将为 Spring Cloud Contract Docker 镜像设置不同的环境变量。spring-doc.cadn.net.cn

#!/bin/bash
set -x

# Setup
# Run the middleware
docker-compose up -d rabbitmq (1)

# Run the python application
gunicorn -w 4 --bind 0.0.0.0 main:app & (2)
APP_PID=$!

docker run  --rm \
                --name verifier \
                -e "STANDALONE_PROTOCOL=rabbitmq" \ (3)
                -e "CAMEL_COMPONENT_RABBITMQ_ADDRESSES=172.18.0.1:5672" \ (4)
                -e "PUBLISH_STUBS_TO_SCM=false" \
                -e "PUBLISH_ARTIFACTS=false" \
                -e "APPLICATION_BASE_URL=172.18.0.1" \
                -e "PROJECT_NAME=application" \
                -e "PROJECT_GROUP=group" \
                -e "EXTERNAL_CONTRACTS_ARTIFACT_ID=application" \
                -e "EXTERNAL_CONTRACTS_GROUP_ID=group" \
                -e "EXTERNAL_CONTRACTS_VERSION=0.0.1-SNAPSHOT" \
                -v "${CURRENT_DIR}/build/spring-cloud-contract/output:/spring-cloud-contract-output/" \
                springcloud/spring-cloud-contract:"${SC_CONTRACT_DOCKER_VERSION}"


# Teardown
kill $APP_PID
yes | docker-compose kill
1 我们需要先让中间件运行起来
2 应用程序需要上线并运行
3 通过STANDALONE_PROTOCOL环境变量,我们将获取一个Apache Camel组件。我们要取回的神器是org.apache.camel.springboot:camel-${STANDALONE_PROTOCOL}-starter.换句话说STANDALONE_PROTOCOL与Camel分量匹配。
4 我们通过Camel的Spring Boot Starter机制设置地址(可能是设置凭证)。Apache Camel RabbitMQ Spring Boot 自动配置示例

Stub Runner Docker 与运行中的中间件

为了在运行中的中间件中触发存根消息,我们可以以以下方式运行 Stub Runner Docker 映像。spring-doc.cadn.net.cn

$ docker run \
    -e "CAMEL_COMPONENT_RABBITMQ_ADDRESSES=172.18.0.1:5672" \ (1)
    -e "SPRING_CLOUD_CONTRACT_STUBRUNNER_IDS=group:application:0.0.1-SNAPSHOT" \ (2)
    -e "SPRING_CLOUD_CONTRACT_STUBRUNNER_REPOSITORY_ROOT=git://https://github.com/marcingrzejszczak/cdct_python_contracts.git" \ (3)
    -e ADDITIONAL_OPTS="--thin.properties.dependencies.rabbitmq=org.apache.camel.springboot:camel-rabbitmq-starter:3.4.0" \ (4)
    -e "SPRING_CLOUD_CONTRACT_STUBRUNNER_STUBS_MODE=REMOTE" \ (5)
    -v "${HOME}/.m2/:/home/scc/.m2:rw" \ (6)
    -p 8750:8750 \ (7)
    springcloud/spring-cloud-contract-stub-runner:3.0.4-SNAPSHOT (8)
1 我们通过Apache Camel的Spring Boot自动配置注入RabbitMQ的地址
2 我们正在告诉Stub Runner要下载哪些小作品
3 我们为我们的存根提供了一个外部位置(Git 仓库)
4 通过ADDITIONAL_OPTS=--thin.properties.dependencies.XXX=GROUP:ARTIFACT:VERSION我们告诉 Stub Runner 在运行时要取哪个额外的依赖。在这种情况下,我们想要取骆驼-兔子-起始者所以XXX是随机字符串,我们想要取org.apache.camel.springboot:骆驼-rabbitmq-starterArtifact 版本3.4.0.
5 因为我们用的是 Git,需要设置远程获取存根的选项
6 为了加快Stub Runner的发布,我们附上了本地的Maven仓库.m2作为一卷。如果你还没填充,可以考虑通过以下方式设置写权限:乌尔曼而是只读:罗.
7 我们暴露端口8750而Stub Runner正在那里奔跑。
8 Stub Runner Docker 镜像的坐标。

过了一会儿,你会在控制台上看到以下提示,表示Stub Runner已经准备好接受请求了。spring-doc.cadn.net.cn

o.a.c.impl.engine.AbstractCamelContext   : Apache Camel 3.4.3 (camel-1) started in 0.007 seconds
o.s.c.c.s.server.StubRunnerBoot          : Started StubRunnerBoot in 14.483 seconds (JVM running for 18.666)
o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
o.s.web.servlet.DispatcherServlet        : Completed initialization in 2 ms

要获得触发器列表,你可以发送HTTP GET请求到localhost:8750/triggers端点。要触发存根消息,你可以发送HTTP POST请求到localhost:8750/triggers/standalone_ping_pong.在控制台上你会看到:spring-doc.cadn.net.cn

o.s.c.c.v.m.camel.CamelStubMessages      : Will send a message to URI [rabbitmq:output?routingKey=#&queue=output]

如果你查看RabbitMQ管理控制台,你会看到在输出队列。spring-doc.cadn.net.cn