微服务pact测试框架
最近,我的一位同事偶然发现了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
微服务pact测试框架