spring 消息传递机制_Spring再次涵盖了您:继续进行消费者驱动的消息传递合同测试...

spring 消息传递机制

在上一篇文章中,我们已经开始讨论基于消息的通信中的消费者驱动的合同测试 。 在今天的帖子中,我们将在测试工具箱中包含另一个工具,但是在此之前,让我对显微镜下的系统进行快速回顾。 它有两项服务, 订单服务货运服务订单服务将消息/事件发布到消息队列,然后运货服务从那里使用它们。

通过寻找合适的测试支架,我们发现了Pact框架(准确地说是Pact JVM )。 该协议提供了编写消费者和生产者测试的简单明了的方法,没有为不进行消费者驱动的合同测试提供任何借口。 但是,该领域还有另一个参与者Spring Cloud Contract ,这就是我们今天要讨论的内容。

首先, Spring Cloud Contract适合基于最佳的基于JVM的项目,该项目建立在出色的Spring产品组合之上(尽管您也可以使其在多语言场景中工作)。 另外, Spring Cloud Contract采用的协作流程与Pact教给我们的协作流程略有不同,这不一定是一件坏事。 让我们直接说清楚。

由于我们只研究消息传递,因此Spring Cloud Contract要求我们要做的第一件事就是定义消息传递协议规范,该规范是使用便捷的Groovy Contract DSL编写的。

 package contracts  org.springframework.cloud.contract.spec.Contract.make { name "OrderConfirmed Event" label 'order'     input { 'createOrder()' triggeredBy( 'createOrder()' ) }     outputMessage { sentTo 'orders'         body([ orderId: $(anyUuid()), paymentId: $(anyUuid()), amount: $(anyDouble()), street: $(anyNonBlankString()), city: $(anyNonBlankString()), state: $(regex( '[AZ]{2}' )), zip: $(regex( '[0-9]{5}' )), country: $(anyOf( 'USA' , 'Mexico' )) ])         headers { header( 'Content-Type' , 'application/json' ) } }  } 

它类似于我们已经熟悉的许多Pact规范(如果您不是Groovy的忠实拥护者 ,则不需要真正学习它即可使用Spring Cloud Contract )。 这里有趣的部分是triggeredBysentTo块:基本上,这些轮廓是如何被生成的消息(或触发),并且其中它应该分别着陆(通道或队列名称)。 在这种情况下, createOrder()只是方法名称,我们必须为其提供实现。

 package com.example.order;  import java.math.BigDecimal;  import java.util.UUID;  import org.junit.runner.RunWith;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.boot.test.context.SpringBootTest;  import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier;  import org.springframework.integration.support.MessageBuilder;  import org.springframework.messaging.MessageChannel;  import org.springframework.test.context.junit4.SpringRunner;  import com.example.order.event.OrderConfirmed;  @RunWith (SpringRunner. class )  @SpringBootTest  @AutoConfigureMessageVerifier  public class OrderBase { @Autowired private MessageChannel orders;     public void createOrder() { final OrderConfirmed order = new OrderConfirmed(); order.setOrderId(UUID.randomUUID()); order.setPaymentId(UUID.randomUUID()); order.setAmount( new BigDecimal( "102.32" )); order.setStreet( "1203 Westmisnter Blvrd" ); order.setCity( "Westminster" ); order.setCountry( "USA" ); order.setState( "MI" ); order.setZip( "92239" ); orders.send( MessageBuilder .withPayload(order) .setHeader( "Content-Type" , "application/json" ) .build()); }  } 

不过,这里只剩下一个小细节:这些合同是由提供者(或更确切地说,生产者)而不是消费者来管理的。 不仅如此,生产者有责任为消费者发布所有存根,以便他们能够针对其编写测试。 当然,与Pact所采用的路径不同,但是从好的方面来说,针对生产者的测试套件是由Apache Maven / Gradle插件100%生成的。

 < plugin > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-contract-maven-plugin</ artifactId > < version >2.1.4.RELEASE</ version > < extensions >true</ extensions > < configuration > < packageWithBaseClasses >com.example.order</ packageWithBaseClasses > </ configuration >  </ plugin > 

您可能已经注意到,该插件将假定基本测试类(必须提供createOrder()方法实现的那些类)位于com.example.order包中,即我们放置OrderBase类的确切位置。 要完成设置,我们需要向pom.xml文件中添加一些依赖项。

 < dependencyManagement > < dependencies > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-dependencies</ artifactId > < version >Greenwich.SR4</ version > < type >pom</ type > < scope >import</ scope > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-dependencies</ artifactId > < version >2.1.10.RELEASE</ version > < type >pom</ type > < scope >import</ scope > </ dependency > </ dependencies >  </ dependencyManagement >  < dependencies > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-contract-verifier</ artifactId > < scope >test</ scope > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency >  </ dependencies > 

而且我们已经完成了生产者方面的工作! 如果我们现在运行mvn clean install ,将发生两件事。 首先,您会注意到已经运行并通过了一些测试,尽管我们没有编写任何测试,但这些测试都是以我们的名义生成的。

 ------------------------------------------------------- TESTS  -------------------------------------------------------  Running com.example.order.OrderTest  ....  Results :  Tests run: 1 , Failures: 0 , Errors: 0 , Skipped: 0 

其次,也将生成(发布)针对消费者的存根(在这种情况下,将其捆绑到order-service-messaging-contract-tests-0.0.1-SNAPSHOT-stubs.jar中 )。

 ...  [INFO]  [INFO] --- spring-cloud-contract-maven-plugin: 2.1 . 4 .RELEASE:generateStubs ( default -generateStubs) @ order-service-messaging-contract-tests --- .RELEASE:generateStubs (  [INFO] Files matching this pattern will be excluded from stubs generation [] [INFO] Files matching pattern will be excluded from stubs generation []  [INFO] Building jar: order-service-messaging-contract-tests- 0.0 . 1 -SNAPSHOT-stubs.jar  [INFO]  .... 

太好了,因此我们已经发布了消息传递合同规范和存根,现在就在消费者的领域,即Shipment Service 。 消费者最棘手的部分可能是配置所选的消息传递集成库。 在我们的案例中,它将是Spring Cloud Stream,但是也可以使用其他集成 。

理解Spring Cloud Contract在消费者方面如何工作的最快方法是从头开始,并首先查看完整的示例测试套件。

 @RunWith (SpringRunner. class )  @SpringBootTest  @AutoConfigureMessageVerifier  @AutoConfigureStubRunner ( ids = "com.example:order-service-messaging-contract-tests:+:stubs" , stubsMode = StubRunnerProperties.StubsMode.LOCAL  )  public class OrderMessagingContractTest { @Autowired private MessageVerifier<Message<?>> verifier; @Autowired private StubFinder stubFinder; @Test public void testOrderConfirmed() throws Exception { stubFinder.trigger( "order" );         final Message<?> message = verifier.receive( "orders" ); assertThat(message, notNullValue()); assertThat(message.getPayload(), isJson( allOf(List.of( withJsonPath( "$.orderId" ), withJsonPath( "$.paymentId" ), withJsonPath( "$.amount" ), withJsonPath( "$.street" ), withJsonPath( "$.city" ), withJsonPath( "$.state" ), withJsonPath( "$.zip" ), withJsonPath( "$.country" ) )))); }  } 

在最上方, @AutoConfigureStubRunner引用生产者发布的存根,有效地来自order-service-messaging-contract-tests-0.0.1-SNAPSHOT-stubs.jar存档中的存根StubFinder通过调用stubFinder.trigger(“ order”)帮助我们为测试用例选择正确的存根,并触发特定的消息传递合同验证流程。 “ order”值不是任意的,它应与分配给合同规范的标签匹配,在我们的示例中,我们将其定义为:

 package contracts  org.springframework.cloud.contract.spec.Contract.make { ... label 'order' ...  } 

这样,测试应该看起来简单而直接:触发流程,验证消息是否已放入消息传递通道并满足消费者的期望。 从配置的角度来看,我们只需要提供此消息传递通道即可运行测试。

 @SpringBootConfiguration  public class OrderMessagingConfiguration { @Bean PollableChannel orders() { return MessageChannels.queue().get(); }  } 

再说一次,bean的名称orders不是一个随机选择,它必须从合同规范中获取很多目的地:

 package contracts  org.springframework.cloud.contract.spec.Contract.make { ... outputMessage { sentTo 'orders' ... } ...  } 

最后但并非最不重要的一点,让我们枚举使用者方面所需的依赖关系(幸运的是,无需使用任何其他的Apache Maven或Gradle插件)。

 < dependencyManagement > < dependencies > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-dependencies</ artifactId > < version >Greenwich.SR4</ version > < type >pom</ type > < scope >import</ scope > </ dependency > </ dependencies >  </ dependencyManagement >  < dependencies > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-contract-verifier</ artifactId > < scope >test</ scope > </ 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</ artifactId > < version >2.2.1.RELEASE</ version > < type >test-jar</ type > < scope >test</ scope > < classifier >test-binder</ classifier > </ dependency >  </ dependencies > 

在这里快速说明。 最后一个依赖关系是一个很重要的难题,它带来了Spring Cloud Stream与Spring Cloud Contract的集成。 这样,消费者就全都准备好了。

 ------------------------------------------------------- TESTS  -------------------------------------------------------  Running com.example.order.OrderMessagingContractTest  ...  Results :  Tests run: 1 , Failures: 0 , Errors: 0 , Skipped: 0 

为了结束循环,我们应该回顾消费者驱动的合同测试的核心承诺之一:允许生产者在不破坏消费者的情况下发展合同。 实际上,这意味着消费者可以将测试归还给生产者,尽管这样做的轻率性与Spring Cloud Contract无关 。 原因很简单:生产者是那些首先编写消息合同规范的人,并且期望从这些规范中生成的测试无法抵御任何重大更改。 尽管如此,对于生产者来说,了解消费者如何使用他们的消息还是有很多好处的,所以请给我一些想法。

满怀希望,这是一个有趣的话题。 Spring Cloud Contract带来了将消费者驱动的合约测试应用于消息传递的不同观点。 它是Pact JVM的一个有吸引力的替代方法,特别是如果您的应用程序和服务已经依赖Spring项目 。

与往常一样,完整的项目资源可在Github上找到 。

翻译自: https://www.javacodegeeks.com/2019/12/spring-covered-again-consumer-driven-contract-testing-messaging-continued.html

spring 消息传递机制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

接口 DataInput

java.io接口 DataInput 所有已知子接口&#xff1a;ImageInputStream, ImageOutputStream, ObjectInput所有已知实现类&#xff1a;DataInputStream, FileCacheImageInputStream, FileCacheImageOutputStream, FileImageInputStream, FileImageOutputStream, ImageInputStreamI…

java反射机制总结

【0】README 0.1&#xff09;以下内容转自&#xff1a; http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html 0.2&#xff09;for source code, please visit &#xff08;1~14 source code : https://github.com/pacosonTang/core-java-volume/blob/master…

c语言系统时间的作用,C语言得到当前系统时间

void getTime(){//获取当前系统时间time_t tTime;//距离1900年1月1日的秒数char str[80];struct tm* stTim;//时间结构time(&tTime);stTim localtime(&tTime);strftime(str,sizeof(str),"%Y%m%d%T",stTim);//格式化时间printf(str);}格式化时间的格式%a 星期…

aws集群重启_使用自动伸缩组在AWS中运行安全数据库集群

aws集群重启当您必须在AWS上运行可扩展应用程序时&#xff0c;您的数据库也必须是可扩展的。 扩展无状态应用程序层更容易&#xff0c;在无状态应用程序层中&#xff0c;每个节点几乎都是一次性的-即使3节点集群中的一个节点发生故障&#xff0c;您也可以启动另一个节点&#x…

接口 DataOutput

java.io 接口 DataOutput 所有已知子接口&#xff1a; ImageOutputStream, ObjectOutput 所有已知实现类&#xff1a; DataOutputStream, FileCacheImageOutputStream, FileImageOutputStream, ImageOutputStreamImpl, MemoryCacheImageOutputStream, ObjectOutputStream, Rand…

java流与文件——流

【0】README 0.1&#xff09; 本文描述转自 core java volume 2&#xff0c; 旨在理解 java流与文件——流 的相关知识&#xff1b; 0.2&#xff09; 输入流和输出流&#xff08;InputStream 和 OutputStream传输单位是基于单字节&#xff09;&#xff1a; 0.2.1&#xff09…

c语言结构体定义字符串数组,C语言,结构体中字符串的声明(采用字符指针还是字符数组)...

结构体中&#xff0c;字符串选项是用字符数组表示好&#xff0c;还是用字符指针表示好&#xff1f;typedef struct person{char *name;int age;char sex[6];}&#xff1b;该结构体中name用的是指针而不是数组&#xff0c;所以需要给字符串在堆上申请内存然后再赋值&#xff1b;…

java –cp ./:_成为Java流专家–第2部分:中级操作

java –cp ./:就像魔术棒一样&#xff0c;中间操作将一个Stream转换为另一个Stream。 这些操作可以无穷无尽的方式组合在一起&#xff0c;以可读有效的方式执行从简单到高度复杂的任务。 本文是五分之二&#xff0c;其中还有一个GitHub存储库&#xff0c;其中包含每个单元的说…

c语言编程代码对父母感恩,c语言中编程:每个做父母的都关心自己孩子成人后孩子的生高:...

c语言中编程&#xff1a;每个做父母的都关心自己孩子成人后孩子的生高&#xff1a;据有关生理卫生知识与数理统计分析表明,影响小孩成人后的身高的因素包括遗传、饮食习惯与体育锻炼等.小孩成人后的身高与其父母的身高和自身的性别密切相关.设faHeight为其父身高,moHeight为其母…

Servlet之javaweb应用(二)

一、 使用 JavaEE 版的 Eclipse 开发动态的 WEB 工程(JavaWEB 项目) 1). 把开发选项切换到 JavaEE 2). 可以在 Window -> Show View 中找到 Package Explorer, 并把其拖拽到开发区的左边 3). 在 Servers 面板中新建 Tomcat 服务器. 一定要关联到 Tomcat 安装的根目录 4). 新…

java流与文件——文本输入输出

【0】README 0.1&#xff09; 本文描述转自 core java volume 2&#xff0c; 旨在理解 java流与文件——文本输入输出 的相关知识&#xff1b; 0.2&#xff09; 在保存数据时&#xff0c;可以选择是二进制还是文本格式&#xff1b; 在存储文本字符串时&#xff0c; 需要考虑字…

RandomAccessFile类解析

【0】README 0.1&#xff09; 本文描述转自 core java volume 2&#xff0c; 旨在理解 java流与文件——RandomAccessFile类解析 的相关知识&#xff1b; 0.1&#xff09; 本文 转自&#xff1a; http://blog.csdn.net/akon_vm/article/details/7429245 &#xff0c; for com…

Servlet之Tomcat配置与启动(一)

一、 部署并启动 tomcat 服务器 1). 解压 apache-tomcat-7.0.11.zip 到一个非中文目录下 2). 配置一个环境变量 java_home(指向 JDK 安装的根目录) 或 jre_home 3). 通过双击 apache-tomcat-6.0.16\bin 目录下的 startup.bat, 启动服务器 4). 可以在浏览器中输入 localhost:8…

随机数生成器c语言,句子随机生成器-怎么用C语言生成随机数

为随机数生成器初始化一个种子值在易语言中使用什么命令名置随机数种子 ()‘调用格式&#xff1a; 〈无返回值〉 置随机数种子 (〔整数型 欲置入的种子数值〕) - 系统核心支持库->算术运算英文名称&#xff1a;randomize为随机数生成器初始化一个种子值&#xff0c;不同的种…

nsstring 空值比较_用比较器的nulls排序具有空值的列表

nsstring 空值比较你好朋友&#xff0c; 在本教程中&#xff0c;我们将看到如何使用Java 8 Comparator.nullsFirst在列表中的项目很少为空时如何对项目列表进行排序&#xff0c;从而将null视为列表中的最小元素。 –什么是比较器 – nullsFirst方法在Comparator中做什么 –…

hibernate的Configuration和配置文件

一、hibernate的入口Configuration 在Hibernate中&#xff0c;Configuration是hibernate的入口。在实例化一个Configuration的时候&#xff0c;Hibernate会自动在环境变量&#xff08;classpath&#xff09;里面查找Hibernate配置文件hibernate.properties。如果该文件存在&…

单片机c语言6种开方,单片机快速开平方的算法

C语言中开平方的算法中要开平方的话,可以在头文件中加#include .然后调sqrt(n);函数即可.但在单片机中要开平方.可以用到下面算法:算法1:本算法只采用移位、加减法、判断和循环实现&#xff0c;因为它不需要浮点运算&#xff0c;也不需要乘除运算&#xff0c;因此可以很方便地运…

spring 配置只读事务_只读副本和Spring Data第3部分:配置两个实体管理器

spring 配置只读事务我们之前的设置可以正常工作。 我们现在要做的是进一步发展&#xff0c;并配置两个单独的实体管理器&#xff0c;而不会影响我们之前实现的功能。 第一步是将默认实体管理器配置设置为主要配置。 这是第一步 package com.gkatzioura.springdatareadreplic…

java流与文件——读写二进制数据(DataOutput + DataInput)

【0】README 0.1&#xff09; 本文描述转自 core java volume 2&#xff0c; 旨在理解 java流与文件——读写二进制数据&#xff08;DataOutput DataInput&#xff09;的相关知识&#xff1b; 0.2&#xff09; for complete my diy code, please visit https://github.com/p…

dsp课程设计c语言源码,DSP课程设计-基于C语言实现256点的FFT精选.pdf

DSP课程设计-基于C语言实现256点的FFT精选XX 大学J1111111 UNIVERSITYDSP 课 程 设 计基于CCS 的FFT 算法的C 语言实现和验证学院名称&#xff1a;专业班级&#xff1a;学 号&#xff1a;学生姓名&#xff1a;指导教师姓名&#xff1a;201 年 0 月 0 日一、 课程设计目的1.此次…