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

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

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

相关文章

Android两个tab吸顶,Android scrollView和viewpager嵌套 指示器吸顶 根据viewpager每

Android scrollView和viewpager嵌套 指示器吸顶 根据viewpager每Android scrollView和viewpager嵌套 指示器吸顶 根据viewpager每个页面的内容适配高度这几天 朋友问我了个问题 有个特别的需求 页面如下就是当viewpager里面的当前页面内容足够多的时候 要去能滑上去 并且指示…

html5input输入框设置无边框_芯片充电两大改变,无看点的iPad8,上手体验发现并不简单!...

前不久&#xff0c;苹果召开了秋季新品发布会&#xff0c;但与以往不同的是&#xff0c;往年本该成为“配角”的iPad&#xff0c;没想到此次成为了主角之一&#xff0c;面对着外观不变仅升级芯片新发布的iPad 8&#xff0c;大家好像没有过多的激情&#xff0c;”旧瓶装新酒“的…

android系统三防机,这才是真正给老人设计的智能手机:三防+安卓系统+超大音量,AGM H2...

原标题&#xff1a;这才是真正给老人设计的智能手机&#xff1a;三防安卓系统超大音量&#xff0c;AGM H2在这个互联网时代&#xff0c;很多智能手机厂商&#xff0c;都是在硬件配置上面进行比拼&#xff0c;包括但是不限于处理器的升级&#xff0c;摄像头的升级&#xff0c;散…

spring aop 注释_使用Spring AOP,自定义注释和反射为您的应用程序审核基础结构

spring aop 注释下一篇文章将演示如何使用Spring AOP和注释编写简单的审计。 审核机制将是干净&#xff0c;高效且易于维护的&#xff08;和Kewwl&#xff01;&#xff09;。 我将在用户管理系统上演示我的示例&#xff08;假设您具有反射和AOP的一般知识&#xff09;。 我们…

springboot 打包_springboot打包-体积太大怎么办

springcloud项目打包动辄100多兆&#xff0c;在文件上传部署的时候非常耗时&#xff0c;多数情况下是毫无意义的耗时&#xff0c;因为依赖包很多情况下不需要改变&#xff0c;只是修改了业务逻辑&#xff0c;那么每次打包上传的时间都浪费了&#xff0c;尤其在开发环境下&#…

.vue文件_Spring Boot 2.x(十六):玩转vue文件上传

为什么使用Vue-Simple-Uploader 最近用到了Vue Spring Boot来完成文件上传的操作&#xff0c;踩了一些坑&#xff0c;对比了一些Vue的组件&#xff0c;发现了一个很好用的组件——Vue-Simple-Uploader&#xff0c;先附上gayhub的&#xff0c;再说说为什么选用这个组件&#xf…

成为Java流专家–第2部分:中级操作

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

HTML怎么在li中加select标签,自定义UL LI选择框似乎在其他HTML元素后面

我似乎无法弄清楚为什么我的自定义UL LI选择框出现在其他HTML元素后面。你如何解决这个问题&#xff0c;当用户点击选择框时&#xff0c;它会出现在其他页面元素的顶部&#xff1f;这里是手头的问题的一个画面&#xff1a; 下面是一个描绘所期望的结果&#xff1a; 这里是有问题…

java初学者面试_Java面试的前50个问题,面向初学者和经验丰富的程序员

java初学者面试您可以参加任何Java面试&#xff0c;无论是大四还是中级&#xff0c;经验或新来的人&#xff0c;一定会看到线​​程&#xff0c;并发和多线程中的几个问题。 实际上&#xff0c;这种内置的并发支持是Java编程语言的最强优势之一&#xff0c;并帮助它在企业界和程…

convert.todatetime指定日期格式_SQL基础知识V2——常用日期函数

点击上方SQL数据库开发&#xff0c;关注获取SQL视频教程SQL专栏SQL数据库基础知识汇总SQL数据库高级知识汇总日期函数是数据库中经常需要使用到的&#xff0c;本期将常用的几个日期函数给小伙伴做详细的介绍。GETDATE()GETDATE()函数用于返回当前数据库系统的日期和时间&#x…

恢复html的初始选定状态,Adobe Photoshop

了解如何在 Adobe Photoshop 中使用“还原/重做”命令和“历史记录”面板来控制图像的状态。通过使用“还原/重做”命令和“历史记录”面板&#xff0c;您可以轻松地控制图像的状态。使用还原或重做命令Photoshop CC 20.0(2018 年 10 月版)中的更新功能从 Photoshop CC 2018 年…

classcastexception异常_优雅的异常处理

代码正常运行不会出问题&#xff0c;但是遇到意外&#xff0c;参数变量&#xff0c;不符合要求&#xff0c;发生意外&#xff0c;代码终止运行代码中的异常处理好了&#xff0c;代码就可以顺利的继续运行&#xff01;3.3 最近我们遇到过的异常System.out.println(1/0);//java.l…

Spring Boot微服务,Docker和Kubernetes研讨会–第3部分

在之前的文章中&#xff0c;我们为使用Docker和Spring Boot的订单管理系统构建了一些微服务&#xff08;订单服务&#xff0c;产品服务&#xff0c;客户服务&#xff09;。 我们使用Netflix库来管理&#xff0c;发现和平衡微服务。 管理这些微服务及其多个容器可能会有些棘手&…

2021年茂名市高考成绩查询,2021年茂名高考最高分多少分,历年茂名高考状元

2021年茂名高考成绩公布时&#xff0c;茂名高考成绩最高分受到很多网友关注&#xff0c;具体2021年茂名高考最高分多少分&#xff0c;考生可以在聚志愿网站查询具体位次排名&#xff0c;报考茂名高考一分一段表位次排名、同分数人数、位次查询等相关数据。本期文章小编主要为大…

客制化键盘键位修改_可以用很漂亮形容的一把键盘,差一步就完美

内置钢板是轴体固定需要也是机械键盘的标志&#xff0c;钢板除了可以带来极其稳定的固定效果也成就了机械键盘扎实的手感&#xff0c;同时是机械键盘分量感的主要来源&#xff0c;给人一种结实感&#xff0c;这是薄膜键帽所不具备的。▲外置钢板在悬浮式结构的键盘上比较常见&a…

adb 切换默认桌面_公告 | 武林外传手游官方服务器全面开放桌面版体验

为了更好的优化玩家游戏体验&#xff0c;应广大客官要求&#xff0c;《武林外传手游》全新桌面版今日上线&#xff0c;iOS及安卓服务器均可在电脑上畅玩《武林外传手游》啦&#xff01;大屏画面更加细腻绚丽&#xff0c;预设键位助你畅游江湖&#xff0c;欢迎广大玩家下载体验&…

java获取word书签表格数据_Python读取word文档里面的表格数据

更多精彩&#xff0c;请点击上方蓝字关注我们&#xff01;我们常见的办公数据通常可以分为结构化数据与非结构化数据&#xff0c;比如常见的word, ppt, excel。前两者存储的是非结构化数据&#xff0c;excel存储的是结构化数据。从事数据统计或分析的工作或多或少都会从excel获…

abb智能控制系统_ABB助力国网冀北电力打造虚拟电厂

近日&#xff0c;ABB为国网冀北电力有限公司定制了智能配电计量与协调控制解决方案&#xff0c;对其虚拟电厂进行远程电能管理&#xff0c;实现高峰调节和负载转移&#xff0c;提高电力系统效率&#xff0c;保持供电稳定性。虚拟电厂是通过分布式电力管理系统将电网中发电端(尤…

通过通用数据访问扩展AWS生态系统

Amazon Web Services&#xff08;AWS&#xff09;可帮助组织托管和管理其数据流程&#xff0c;例如构建数据可视化和执行ETL任务。 在CData&#xff0c;我们可以轻松地将AWS Services与异构业务应用程序和分布式数据存储连接起来&#xff0c;以最终帮助企业对其数据进行更全面的…

android官方文档中文版_Now in Android:01 - 如何掌握最新的 Android 技术?

每隔几天我都会通过 Android Developers 的油管官方频道&#xff0c;来了解一下最近 Android 发布了哪些有趣的新技术&#xff0c;最近发现官方推出了一个新的系列视频叫做&#xff1a;Now in Android&#xff0c;目前更新了 4 期&#xff0c;我觉得这个系列蛮有趣的&#xff0…