消费者驱动的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 {
    @Rule
    public 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;
    
    @TestTarget
    public final Target target = new HttpTarget(8080);
    
    @BeforeClass
    public 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");
    }

    @AfterClass
    public 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://www.javacodegeeks.com/2017/03/consumer-driven-testing-pact-spring-boot.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值