Spring Cloud Contract 契约测试简介

标签: | 发表时间:2021-12-06 14:23 | 作者:
出处:https://www.baeldung.com

一、介绍

Spring Cloud Contract是一个项目,简单地说,就是帮助我们编写 消费者驱动的合同(CDC)

这确保了分布式系统中 ProducerConsumer之间的契约——用于基于 HTTP 和基于消息的交互。

在这篇快速文章中,我们将探索通过 HTTP 交互为 Spring Cloud Contract 编写生产者和消费者端测试用例。

2. 生产者 – 服务器端

我们将编写一个生产者端 CDC,以 EvenOddController的形式——它只是告诉 数字参数是偶数还是奇数:

  @RestController
public class EvenOddController {

    @GetMapping("/validate/prime-number")
    public String isNumberPrime(@RequestParam("number") Integer number) {
        return Integer.parseInt(number) % 2 == 0 ? "Even" : "Odd";
    }
}

2.1. Maven 依赖项

对于我们的生产者方面,我们需要 spring-cloud-starter-contract-verifier依赖项:

  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-contract-verifier</artifactId>
    <version>2.1.1.RELEASE</version>
    <scope>test</scope>
</dependency>

我们需要使用我们的基本测试类的名称配置 spring-cloud-contract-maven-plugin,我们将在下一节中描述:

  <plugin>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <version>2.1.1.RELEASE</version>
    <extensions>true</extensions>
    <configuration>
        <baseClassForTests>
            com.baeldung.spring.cloud.springcloudcontractproducer.BaseTestClass
        </baseClassForTests>
    </configuration>
</plugin>

2.2. 生产者端设置

我们需要在加载 Spring 上下文的测试包中添加一个基类:

  @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@DirtiesContext
@AutoConfigureMessageVerifier
public class BaseTestClass {

    @Autowired
    private EvenOddController evenOddController;

    @Before
    public void setup() {
        StandaloneMockMvcBuilder standaloneMockMvcBuilder 
          = MockMvcBuilders.standaloneSetup(evenOddController);
        RestAssuredMockMvc.standaloneSetup(standaloneMockMvcBuilder);
    }
}

/src/test/resources/contracts/包中,我们将添加测试存根,例如文件 shouldReturnEvenWhenRequestParamIsEven.groovy中的 这个

  import org.springframework.cloud.contract.spec.Contract
Contract.make {
    description "should return even when number input is even"
    request{
        method GET()
        url("/validate/prime-number") {
            queryParameters {
                parameter("number", "2")
            }
        }
    }
    response {
        body("Even")
        status 200
    }
}

当我们运行构建时,插件会自动生成一个名为 ContractVerifierTest的测试类,它扩展了我们的 BaseTestClass并将其放在 /target/generated-test-sources/contracts/ 中

测试方法的名称源自前缀“  validate_”与我们的 Groovy 测试存根的名称连接。对于上述 Groovy 文件,生成的方法名称将为 “validate_shouldReturnEvenWhenRequestParamIsEven”

让我们看看这个自动生成的测试类:

  public class ContractVerifierTest extends BaseTestClass {

@Test
public void validate_shouldReturnEvenWhenRequestParamIsEven() throws Exception {
    // given:
    MockMvcRequestSpecification request = given();

    // when:
    ResponseOptions response = given().spec(request)
      .queryParam("number","2")
      .get("/validate/prime-number");

    // then:
    assertThat(response.statusCode()).isEqualTo(200);
    
    // and:
    String responseBody = response.getBody().asString();
    assertThat(responseBody).isEqualTo("Even");
}

构建还将在我们的本地 Maven 存储库中添加存根 jar,以便我们的使用者可以使用它。

存根将出现在 stubs/mapping/下的输出文件夹中。

3. 消费者 – 客户端

我们CDC的消费者端会通过HTTP交互消费生产者端生成的stub来维护合约,所以生产者端的任何变化都会破坏合约。

我们将添加 BasicMathController,它将发出 HTTP 请求以从生成的存根中获取响应:

  @RestController
public class BasicMathController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/calculate")
    public String checkOddAndEven(@RequestParam("number") Integer number) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");

        ResponseEntity<String> responseEntity = restTemplate.exchange(
          "http://localhost:8090/validate/prime-number?number=" + number,
          HttpMethod.GET,
          new HttpEntity<>(httpHeaders),
          String.class);

        return responseEntity.getBody();
    }
}

3.1. Maven 依赖项

对于我们的消费者,我们需要添加 spring-cloud-contract-wiremock spring-cloud-contract-stub-runner依赖项:

  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-wiremock</artifactId>
    <version>2.1.1.RELEASE</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-stub-runner</artifactId>
    <version>2.1.1.RELEASE</version>
    <scope>test</scope>
</dependency>

3.2. 消费者端设置

现在是配置我们的存根运行器的时候了,它将通知我们的消费者我们本地 Maven 存储库中的可用存根:

  @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
@AutoConfigureStubRunner(
  stubsMode = StubRunnerProperties.StubsMode.LOCAL,
  ids = "com.baeldung.spring.cloud:spring-cloud-contract-producer:+:stubs:8090")
public class BasicMathControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void given_WhenPassEvenNumberInQueryParam_ThenReturnEven()
      throws Exception {
 
        mockMvc.perform(MockMvcRequestBuilders.get("/calculate?number=2")
          .contentType(MediaType.APPLICATION_JSON))
          .andExpect(status().isOk())
          .andExpect(content().string("Even"));
    }
}

请注意, @AutoConfigureStubRunner注释的 ids属性指定:

  • com.baeldung.spring.cloud —我们的工件的 groupId
  • spring-cloud-contract-producer —生产者存根 jar的 artifactId
  • 8090 — 生成的存根将在其上运行的端口

4. 合同违约时

如果我们在生产者端进行任何直接影响合约的更改而不更新消费者端,这可能会导致合约失败。

例如,假设我们要将生产者端的 EvenOddController请求 URI 更改/validate/change/prime-number

如果我们没有通知我们的消费者这个变化,消费者仍然会将它的请求发送到 /validate/prime-number URI,消费者端的测试用例将抛出 org.springframework.web.client.HttpClientErrorException: 404 Not Found

5. 总结

我们已经看到 Spring Cloud Contract 如何帮助我们维护服务消费者和生产者之间的契约,以便我们可以推出新代码而不必担心破坏契约。

而且,一如既往,可以 在 GitHub 上找到本教程的完整实现。

相关 [spring cloud contract] 推荐:

Spring Cloud Contract 契约测试简介

- -
Spring Cloud Contract是一个项目,简单地说,就是帮助我们编写 消费者驱动的合同(CDC). 这确保了分布式系统中 Producer和 Consumer之间的契约——用于基于 HTTP 和基于消息的交互. 在这篇快速文章中,我们将探索通过 HTTP 交互为 Spring Cloud Contract 编写生产者和消费者端测试用例.

大话 Spring Cloud

- - IT瘾-dev
研究了一段时间spring boot了准备向spirng cloud进发,公司架构和项目也全面拥抱了Spring Cloud. 在使用了一段时间后发现Spring Cloud从技术架构上降低了对大型系统构建的要求,使我们以非常低的成本(技术或者硬件)搭建一套高效、分布式、容错的平台,但Spring Cloud也不是没有缺点,小型独立的项目不适合使用.

Spring Cloud限流详解 | Spring Cloud|周立

- -
限流往往是一个绕不开的话题. 本文详细探讨在Spring Cloud中如何实现限流. Zuul上实现限流是个不错的选择,只需要编写一个过滤器就可以了,关键在于如何实现限流的算法. 常见的限流算法有漏桶算法以及令牌桶算法. https://www.cnblogs.com/LBSer/p/4083131.html,写得通俗易懂,你值得拥有,我就不拽文了.

Spring Cloud Kubernetes指南

- -
当我们构建微服务解决方案时,SpringCloud和Kubernetes都是最佳解决方案,因为它们为解决最常见的挑战提供组件. 但是,如果我们决定选择Kubernetes作为我们的解决方案的主要容器管理器和部署平台,我们仍然可以主要通过SpringCloudKubernetes项目使用SpringCloud的有趣特性.

Spring Cloud 快速入门

- - IT瘾-tuicool
Spring Cloud 是一套完整的微服务解决方案,基于 Spring Boot 框架,准确的说,它不是一个框架,而是一个大的容器,它将市面上较好的微服务框架集成进来,从而简化了开发者的代码量. 本课程由浅入深带领大家一步步攻克 Spring Cloud 各大模块,接着通过一个实例带领大家了解大型分布式微服务架构的搭建过程,最后深入源码加深对它的了解.

Deploy the spring cloud project using jenkins

- - Telami
先简单记录下Jenkins部署maven聚合工程要点. Root pom配置成项目根目录的pom.xml. maven命令单独install 欲构建的项目. 选项后可跟随{groupId}:{artifactId}或者所选模块的相对路径(多个模块以逗号分隔). 表示同时处理选定模块所依赖的模块. 表示同时处理依赖选定模块的模块.

Spring Cloud Gateway(限流) | Wind Mt

- -
限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击. 一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池、线程池)、限制瞬时并发数(如 nginx 的 limit_conn 模块,用来限制瞬时并发连接数)、限制时间窗口内的平均速率(如 Guava 的 RateLimiter、nginx 的 limit_req 模块,限制每秒的平均速率);其他还有如限制远程接口调用速率、限制 MQ 的消费速率.

快速突击 Spring Cloud Gateway

- - 掘金后端
认识 Spring Cloud Gateway. Spring Cloud Gateway 是一款基于 Spring 5,Project Reactor 以及 Spring Boot 2 构建的 API 网关,是 Spring Cloud 微服务生态的主要组件之一. Spring Cloud Gateway 主要负责接口请求的路由分发,并且支持对请求的安全验证,流量监控和流量控制等扩展操作.

Spring Cloud Gateway2.0实践报告

- - 掘金后端
你的点赞就是对我最大的支持. 原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. 本文将从知识拓扑讲起,谈一下api网关的功能,以及spring cloud gateway的使用方法. 一、知识拓扑 (使用和原理) 二、网关的作用 三、Predicate,路由匹配 四、Filter,过滤器编写 五、自定义过滤器 六、常见问题 复制代码.

微服务框架Spring Cloud介绍 Part2: Spring Cloud与微服务

- - skaka的博客
之前介绍过 微服务的概念与Finagle框架, 这个系列介绍Spring Cloud.. Spring Cloud还是一个相对较新的框架, 今年(2016)才推出1.0的release版本. 虽然Spring Cloud时间最短, 但是相比我之前用过的Dubbo和Finagle, Spring Cloud提供的功能最齐全..