消费者驱动的Pact和Spring Boot测试

最近,我的一位同事偶然发现了Pact.io ,我们的当前应用程序已发展到50多种服务,并且我们开始出现一些集成测试失败和脆弱的开发/验收测试环境。 因此,我们决定研究尝试与此相关的方法。

我从阅读开始: https : //docs.pact.io/faq/convinceme.html

然后观看: https : //www.youtube.com/watch?v = -6x6XBDf9sQ&feature = youtu.be

那两个资源说服了我试一试。

因此,我开始并创建了一组快速的Spring引导应用程序( 此处为GitHub repo),以测试概念并使其正常运行。

突出演示中的一些重要内容。

消费者:

由于Pact是消费者驱动的测试框架。 在这里,您可以定义一个单元测试,该测试模拟http服务器响应,并以此为依据进行断言。

一旦测试成功,它将在/ pacts目录中创建一个pact json文件。

public class TestProvider {@Rulepublic PactProviderRule provider = new PactProviderRule("test_provider", "localhost", 8081, this);@Pact(state = "default", provider = "test_provider", consumer = "test_consumer")public PactFragment createFragment(PactDslWithProvider builder) {Map<String, String> headers = new HashMap<>();headers.put("content-type", "application/json");return builder.given("default").uponReceiving("Test User Service").path("/user/1").method("GET").willRespondWith().status(200).headers(headers).body("{" +"  \"userName\": \"Bob\",\n" +"  \"userId\": \"1\",\n" +"  \"firstName\": null,\n" +"  \"lastName\": null,\n" +"  \"email\": null,\n" +"  \"groups\": null\n" +"}").toFragment();}@Test@PactVerification("test_provider")public void runTest() throws IOException {final RestTemplate call = new RestTemplate();final User expectedResponse = new User();expectedResponse.setUserName("Bob");expectedResponse.setUserId("1");final User forEntity = call.getForObject(provider.getConfig().url() + "/user/1", User.class);assertThat(forEntity, sameBeanAs(expectedResponse));}
}

因此,在运行“模拟”测试并创建协定文件之后。 您需要包括一个maven插件…pact…,然后将其用于将pacts /文件夹的内容发布到pact代理……这在pom中定义如下。

<dependencies><!-- https://mvnrepository.com/artifact/au.com.dius/pact-jvm-consumer-junit_2.11 --><dependency><groupId>au.com.dius</groupId><artifactId>pact-jvm-consumer-junit_2.11</artifactId><version>3.3.6</version><scope>test</scope></dependency>
</dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.18</version><configuration><systemPropertyVariables><pact.rootDir>pacts</pact.rootDir><buildDirectory>${project.build.directory}</buildDirectory></systemPropertyVariables></configuration></plugin><plugin><groupId>au.com.dius</groupId><artifactId>pact-jvm-provider-maven_2.11</artifactId><version>3.3.4</version><configuration><pactDirectory>pacts</pactDirectory><pactBrokerUrl>http://localhost:80</pactBrokerUrl><projectVersion>1.0.1</projectVersion></configuration></plugin></plugins>
</build>

制片人:

这使用来自Pact.io的JUnit集成从代理下载契约,然后针对正在运行的服务运行。

由于这已经使用了@RunWith批注,因此我无法使用spring bootRunner。 因此,为了解决这个问题,在上课之前,我启动了Spring引导应用程序,然后针对该正在运行的实例运行了协定……并且在测试之后,引导应用程序又被停止了。 根据您的用例,我想也可以使用@Before来执行此操作,这样您就可以在每个软件包之前启动一个新的服务实例,但这会极大地降低执行速度。

@State批注允许客户端定义特定的状态,生产者可以使用该状态来设置测试运行所需的其他数据/条件。

一旦对服务执行了契约,目标文件夹中就会生成报告。

@RunWith(PactRunner.class)
@Provider("test_provider" )
@PactBroker(host = "localhost", port = "80")
@VerificationReports({"console", "markdown"})
public class TestPacts {private static ConfigurableApplicationContext application;@TestTargetpublic final Target target = new HttpTarget(8080);@BeforeClasspublic static void startSpring(){application = SpringApplication.run(ProviderServiceApplication.class);}@State("default")public void toDefaultState() {System.out.println("Now service in default state");}@State("extra")public void toExtraState() {System.out.println("Now service in extra state");}@AfterClasspublic static void kill(){application.stop();}
}

设置契约代理

1.从Docker Hub获取公共映像。

docker pull dius/pact_broker
docker pull postgres

2.然后设置Postgres数据库

docker run --name pactbroker-db -e POSTGRES_PASSWORD=ThePostgresPassword -e POSTGRES_USER=admin -d postgres
docker run -it --link pactbroker-db:postgres --rm postgres psql -h postgres -U admin
CREATE USER pactbrokeruser WITH PASSWORD 'TheUserPassword';
CREATE DATABASE pactbroker WITH OWNER pactbrokeruser;
GRANT ALL PRIVILEGES ON DATABASE pactbroker TO pactbrokeruser;

3.数据库启动后,运行实际的代理:

docker run --name pactbroker --link pactbroker-db:postgres -e PACT_BROKER_DATABASE_USERNAME=pactbrokeruser -e PACT_BROKER_DATABASE_PASSWORD=TheUserPassword -e PACT_BROKER_DATABASE_HOST=postgres -e PACT_BROKER_DATABASE_NAME=pactbroker -d -p 80:80 dius/pact_broker

额外参考:

  • https://docs.pact.io/documentation/
  • https://docs.pact.io/documentation/sharings_pacts.html
  • https://github.com/DiUS/pact-jvm
  • https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-consumer-junit

获取示例项目

  • https://github.com/bdupreez/pactdemo

翻译自: https://www.javacodegeeks.com/2017/03/consumer-driven-testing-pact-spring-boot.html

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

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

相关文章

python空格怎么加密_使用Python的RSA加密

如果您想使用python高效地编码RSA加密&#xff0c;我的github存储库肯定会理解和解释python中RSA的数学定义RSA密钥生成def keyGen(): Generate Keypair i_prandint(0,20)i_qrandint(0,20)# Instead of Asking the user for the prime Number which in case is not feasible,# …

MySQL中字符串函数详细介绍

MySQL字符串函数对于针对字符串位置的操作&#xff0c;第一个位置被标记为1。 ASCII(str)返回字符串str的 最左面字符的ASCII代码值。如果str是空字符串&#xff0c; 返回0。如果str是NULL&#xff0c;返回NULL。 mysql> select ASCII(2);-> 50mysql> select ASCII(2)…

java 转储快照分析_分析Java核心转储

java 转储快照分析在本文中&#xff0c;我将向您展示如何调试Java核心文件&#xff0c;以查看导致JVM崩溃的原因。 我将使用在上一篇文章&#xff1a; 生成Java Core Dump中生成的核心文件。 您可以通过以下几种方法来诊断JVM崩溃&#xff1a; hs_err_pid日志文件 当JVM中发生…

zbox mysql_20190213云服务器部署禅道

1.系统环境&#xff1a;腾讯云服务器&#xff1b;Centos 7.02.工具&#xff1a;禅道的压缩包(需要是tar.gz文件名的)、Xshell、Xftp&#xff1b;3.安全组规则的设置&#xff1b;4.端口号的设置以下为详细步骤&#xff1a;需要在空白的服务器上去进行操作。还需要再琢磨的。1、x…

Java编程语言的历史和未来

通过AppDynamics解决应用程序问题的速度提高了10倍–以最小的开销在代码级深度监视生产应用程序。 开始免费试用&#xff01; 作为Internet上著名的编程语言 &#xff0c;Java对人们如何浏览数字世界产生了深远的影响。 Java功能设置了用户对他们访问互联网的设备的性能期望的…

fmdb和mysql的区别_FMDB

什么是数据库数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,我们可以很方便的对数据库中的数据进行增、删、改、查操作数据库类型数据库可以分为2大种类关系型数据库(主流)关系型数据库(主流)对象型数据库常用关系型数据库PC端&#xff1a;Oracle、MySQL、SQL S…

RabbiqMQ快速入门

RabbitMQ 官网地址: https://www.rabbitmq.com/ 一个遵循AMQP协议&#xff0c;开源面向消息的中间件,支持多种编程语言。 Rabbitmq 能做什么? 逻辑解耦&#xff0c;异步的消息任务消息持久化&#xff0c;重启不影响削峰&#xff0c;大规模的消息处理主要的特点 可靠性&#xf…

Java命令行界面(第13部分):JArgs

JArgs 1.0的区别在于&#xff0c;这是我的第13篇文章的主题&#xff0c;该文章是关于Java命令行参数解析的。 JArgs是一个开放源代码&#xff08; BSD许可证 &#xff09;库&#xff0c;主要由Steve Purcell和Ewan Mellor等 不同的贡献者支持。 事实证明&#xff0c;这在第一次…

pthread vs openMP之我见

前两天看了些并行计算的文章&#xff0c;了解了一些并行计算的方法和原理。然后发现多线程实现里面还有个openMP&#xff0c;这个以前从来没见过&#xff08;火星了&#xff09;&#xff0c;之前只是知道pthread线程库和微软也实现了一套线程。又看了看openMP的一些教程才知道它…

线程池默认多少个线程_我需要多少个线程?

线程池默认多少个线程这取决于您的应用程序。 但是&#xff0c;对于那些希望对如何从生产站点购买的所有昂贵内核中挤出大量资金的人&#xff0c;请多多包涵&#xff0c;我将阐明围绕多线程 Java应用程序的奥秘。 内容针对最典型的Java EE应用程序进行了“优化”&#xff0c;该…

mysql error writing_MySQL:Error writing file (Errcode: 28)解决方法

问题描述&#xff1a;在执行创建表语句时提示&#xff1a;mysql> CREATE TABLE cash_request (id int(11) NOT NULL auto_increment,dev_id int(11) NOT NULL,bank_account_info varchar(255) NOT NULL,money int(11) NOT NULL,status tinyint(1) NOT NULL default 1,is_fan…

[暑假集训Day4T3]曲线

三分模板。 三分法求单峰函数最优值,之后每次取所有二次函数最优值即可 #pragma GCC optimize(3,"Ofast","inline") #include<iostream> #include<cstdio> #define N 100005 #define eps 1e-9 using namespace std; int read() {int x0,f1;cha…

模拟Spring Security上下文进行单元测试

今天&#xff0c;在为一种Java方法编写单元测试用例时&#xff0c;如下所示&#xff1a; public ApplicationUser getApplicationUser() {ApplicationUser applicationUser (ApplicationUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();return…

mysql semi-synchronous_MySQL Semisynchronous Replication介绍

前言MySQL 5.5版本之前默认的复制是异步(Asynchronous )模式的, MySQL 5.5 以plugins的方式提供了Semisynchronous Replication 模式。在介绍 semi sync 之前,我们先了解&#xff1a;半同步 Asynchronous 和 同步 Synchronous 。异步复制模式主库将已经提交的事务event 写入bin…

Jquery屏蔽回车键

1 $(function(){2 3 $(“#tagForm input”).keypress(4 5 function(event){6 7 if(event.keyCode 13){8 9 returnfalse;10 11 }12 13 });14 15 })转载于:https://www.cnblogs.com/pfs1314/archive/2011/04/19/2020706.html

滑坡泥石流的防御措施_滑坡泥石流防御

什么是滑坡、泥石流?滑坡是指山坡在河流冲刷、降雨、地震、人工切坡等因素影响下&#xff0c;土层或岩层整体或分散地顺斜坡向下滑动的现象。滑坡也叫地滑&#xff0c;群众中还有“走山”、“垮山”或“山剥皮”等俗称。泥石流是指在降水、溃坝或冰雪融化形成的地面流水作用下…

Event Delegate(代理)异常:该委托必须有一个目标 解决方法

正文待叙转载于:https://www.cnblogs.com/kodong/archive/2013/04/19/3031212.html

自定义注解 实现自定义消息_实现自定义的未来

自定义注解 实现自定义消息上一次我们学习了java.util.concurrent.Future<T>背后的原理 。 我们还发现&#xff0c; Future<T>通常由库或框架返回。 但是&#xff0c;没有什么可以阻止我们在有意义的情况下自行实现所有功能。 它不是特别复杂&#xff0c;可以显着改…

菜单 java_java 菜单

继承体系MenuBar,Menu,MenuItem之间的关系&#xff1a;先创建菜单条&#xff0c;再创建菜单&#xff0c;每一个菜单中建立菜单项。也可以菜单添加到菜单中&#xff0c;作为子菜单。通过setMenuBar()方法&#xff0c;将菜单添加到Frame中。package june610;import java.awt.File…

Jsp、Servlet

1 forward、redirect forward 转发是服务器行为&#xff0c;浏览器根本不知道服务器发送的内容是从哪儿来&#xff0c;所以它的地址栏中还是原来的地址。 redirect 重定向是客户端行为。redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址&#xff0c;一…