Contract 如何保证您的API合乎预期 探秘Spring

  • 电脑网络维修
  • 2024-11-15

微服务集成测试之痛

1.什么是契约测试

契约测试(Contract testing)是一种测试技术,它经过以隔离审核集成点上的每个运行的形式,确保运行发送或接纳的信息合乎调用双方共识,并准许随着期间的推移启动演变。

契约测试是对单元测试的增强,针对服务接口provider测试,笼罩了一局部原本须要集成测试才干测试到的场景。

2.为什么要做契约测试

契约测试关键处置在存在沟通边界状况下,测试替身(Test Double)与消费代码体现或许不分歧的疑问。在契约测试中,契约由代码生成,坚持与事实同步,而且运行可以独立于其它运行而仅基于契约启动极速测试。

由于集成测试容易遭到网络缓慢或无法靠,以及服务无法靠等要素的影响而运转缓慢或失败,所以通常会引入测试替身来替代实在外部服务,以极速成功笼罩度更广的测试,让测试真正起到作用。

3.契约测试的定位

金字塔模型是构建肥壮、极速、可保养测试集的成熟通常。

4.契约测试的价值

妇孺皆知,越是在名目生命周期的前期发现Bug,其修复的老本就越高。

不同于端到端(E2E)测试,契约测试可以在开发人员推送代码之前运转,在开发阶段延迟发现疑问。

契约测试还有很多端到端测试不具有的好处:

引入契约测试,还会带来如下福利:

没有两个团队是齐全一样的,契约测试也不是万能的,关键要看契约测试可认为团队和名目带来什么。

5.契约测试适宜的场景

契约测试可以用于任何须要通讯的两个服务,比如Web前端与后端API服务。

在微服务架构体系中,由于存在更多团队独立、服务间调用及服务独自演进的情形,契约测试有了更好更大的用武之地。良好的契约测试,使得开发人员很容易防止版本天堂,是微服务开发和部署的利器。

6.概念术语

契约测试关键触及如下概念术语:

7.契约测试形式

契约测试分为消费者驱动(consumer-driven)和提供者驱动(Provider-driven)两种形式。

消费者驱动更具哲学意义,将API的消费者置于设计环节的外围,来提倡更好的外部微服务设计。该形式的优势在于,只要消费者正在经常使用的局部会获取测试,而提供者可以自在地更改消费者不经常使用的任何其它局部,而不用破坏任何现有测试。

提供者驱动思绪较为惯例,更适宜放开数据或系统的场景。

无论驳回哪种格调,关键在于取得契约测试的好处,成功引入契约测试的目标。

(1)消费者驱动

消费者驱动的契约测试运转步骤如下:

(2)提供者驱动

提供者驱动形式由提供者定义契约并驱动整个环节。

8.契约测试工具

盛行的契约测试工具为:

9.应用Pact启动消费者驱动的测试价值

应用Pact启动契约测试的整个流程表示如下,经常使用了 pact 之后,依然是每个服务独立的启动单元测试,然而可以模拟出实在集成场景。

10.Pact示例

pact契约测试分为两步:

以下为nlp-pact-parent示例:

(1)父名目pom包相关

<dependencies><dependency><groupId>au.com.dius</groupId><artifactId>pact-jvm-consumer-junit5</artifactId><version>4.0.10</version><scope>test</scope></dependency><dependency><groupId>au.com.dius</groupId><artifactId>pact-jvm-provider-junit5</artifactId><version>4.0.10</version><scope>test</scope></dependency>

(2)nlp-pact-consumer消费端名目

编写ConsumerTest生成契约:

@ExtendWith(PactConsumerTestExt.class)@SpringBootTest(classes = PactConsumerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)@PactTestFor(providerName = "nlp-pact-provider", port = "8202")public class ConsumerTest {private TestRestTemplate restTemplate = new TestRestTemplate();@Test@PactTestFor(pactMethod = "greetingPact")void greeting_shouldReturnMessage() {// ArrangeHttpHeaders headers = new HttpHeaders();headers.add("Content-Type", "application/json");// ActResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:8202/greeting?name=John", Map.class);// AssertassertEquals(HttpStatus.OK, response.getStatusCode());assertEquals(Collections.singletonMap("message", "Hello, John!"), response.getBody());}// Pact 定义@Pact(consumer = "nlp-pact-consumer", provider = "nlp-pact-provider")public RequestResponsePact greetingPact(PactDslWithProvider builder) {return builder.given("a request for greeting with name 'John'").uponReceiving("a request to greet John").path("/greeting").method("GET").query("name=John").willRespondWith().status(200).headers(Collections.singletonMap("Content-Type", "application/json")).body("{\"message\": \"Hello, John!\"}").toPact();}}

(3)口头ConsumerTest测试用例,生成如下契约文件:

# nlp-pact-consumer-nlp-pact-provider.json{"provider": {"name": "nlp-pact-provider"},"consumer": {"name": "nlp-pact-consumer"},"interactions": [{"description": "a request to greet John","request": {"method": "GET","path": "/greeting","query": {"name": ["John"]}},"response": {"status": 200,"headers": {"Content-Type": "application/json"},"body": {"message": "Hello, John!"}},"providerStates": [{"name": "a request for greeting with name 'John'"}]}],"metadata": {"pactSpecification": {"version": "3.0.0"},"pact-jvm": {"version": "4.0.10"}}}

(4)nlp-pact-provider提供端验证契约

build性能如下:

<plugin><groupId>au.com.dius</groupId><artifactId>pact-jvm-provider-maven</artifactId><version>4.0.0</version><configuration><serviceProviders><serviceProvider><name>nlp-pact-provider</name><protocol>http</protocol><host>localhost</host><port>8200</port><path>/</path><pactFileDirectory>resources/pacts</pactFileDirectory></serviceProvider></serviceProviders><pactBrokerUrl/></configuration></plugin>

(5)运转命令:mvn pact:verify,验证契约

Found 1 pact filesVerifying a pact between nlp-pact-consumer and nlp-pact-provider[Using File D:\IdeaProjects\nlp-other-project-dev\nlp-pact-parent\nlp-pact-provider\target\pacts\nlp-pact-consumer-nlp-pact-provider.json]Given a request for greeting with name 'John'WARNING: State Change ignored as there is no stateChange URLa request to greet Johnreturns a response whichhas status code 200 (OK)has a matching body (OK)[WARNING] Skipping publishing of verification results as it has been disabled (pact.verifier.publishResults is not 'true')[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time:1.589 s[INFO] Finished at: 2023-03-08T15:02:33+08:00[INFO] --------

11.Pact Broker

Pact Broker是一个用于共享消费者驱动的合同和验证结果的运行程序。

pact主页面:

检查服务间相关:

与CICD集成:

12.总结

我在不少名目中都尝试过实施契约测试,然而真正实施成功的并不多,关键要素还是规模和痛点不够大,从而造成团队感觉没有必要做,或许感觉做了收益比投入少。而成功的普通的都是团队人员足够痛,或许教训过大型多团队名目中服务扭转等各种痛点,从而造成他们处置自己的痛点而被动实施契约测试,然而前提是他们都知道契约测试。所以要成功实施契约都是有两个关键的前提条件:1,团队关于相关疑问足够痛,2,团队懂契约测试。在这种状况下,团队才或许情愿被动实施契约测试,才干成功的实施契约测试。所以首先是要让开发团队懂契约测试,比如契约测试能处置什么疑问,实施流程,相关测试框架等,然前期待团队无法忍受相关痛点后,成功的实施契约测试就可以水到渠成了。

  • 关注微信

本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载联系作者并注明出处:https://duobeib.com/diannaowangluoweixiu/6934.html

猜你喜欢

热门标签

洗手盆如何疏浚梗塞 洗手盆为何梗塞 iPhone提价霸占4G市场等于原价8折 明码箱怎样设置明码锁 苏泊尔电饭锅保修多久 长城画龙G8253YN彩电输入指令画面变暗疑问检修 彩星彩电解除童锁方法大全 三星笔记本培修点上海 液晶显示器花屏培修视频 燃气热水器不热水要素 热水器不上班经常出现3种处置方法 无氟空调跟有氟空调有什么区别 norltz燃气热水器售后电话 大连站和大连北站哪个离周水子机场近 热水器显示屏亮显示温度不加热 铁猫牌保险箱高效开锁技巧 科技助力安保无忧 创维8R80 汽修 a1265和c3182是什么管 为什么电热水器不能即热 标致空调为什么不冷 神舟培修笔记本培修 dell1420内存更新 青岛自来水公司培修热线电话 包头美的洗衣机全国各市售后服务预定热线号码2024年修缮点降级 创维42k08rd更新 空调为什么运转异响 热水器为何会漏水 该如何处置 什么是可以自己处置的 重庆华帝售后电话 波轮洗衣机荡涤价格 鼎新热水器 留意了!不是水平疑问! 马桶产生了这5个现象 方便 极速 邢台空调移机电话上门服务 扬子空调缺点代码e4是什么疑问 宏基4736zG可以装置W11吗 奥克斯空调培修官方 为什么突然空调滴水很多 乐视s40air刷机包 未联络视的提高方向 官网培修 格力空调售后电话 皇明太阳能电话 看尚X55液晶电视进入工厂形式和软件更新方法 燃气热水器缺点代码

热门资讯

关注我们

微信公众号