首页 > 编程语言 >创建带有合约存根的 Spring REST 应用程序并在另一个 Spring 应用程序中使用该合约的过程

创建带有合约存根的 Spring REST 应用程序并在另一个 Spring 应用程序中使用该合约的过程

时间:2022-12-26 10:02:34浏览次数:43  
标签:java Spring springframework contract 存根 应用程序 org import id

创建带有合约存根的 Spring REST 应用程序并在另一个 Spring 应用程序中使用该合约的过程_应用程序

本指南将引导您完成创建带有合约存根的 Spring REST 应用程序并在另一个 Spring 应用程序中使用该合约的过程。

您将构建的内容

你将设置两个微服务,一个提供其协定,另一个使用此合约,以确保与合约提供程序服务的集成符合规范。如果将来生产者服务的契约发生变化,那么消费者服务的测试将无法捕获潜在的不兼容性。

你需要什么

  • 约15分钟
  • 最喜欢的文本编辑器或 IDE
  • JDK 1.8或以后
  • 格拉德尔 4+​或梅文 3.2+
  • 您也可以将代码直接导入到 IDE 中:
  • 弹簧工具套件 (STS)
  • 智能理念
  • VSCode

如何完成本指南

像大多数春天一样入门指南,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都会得到工作代码。

要从头开始,请继续使用 Gradle 构建.

要跳过基础知识,请执行以下操作:

  • 下载​并解压缩本指南的源存储库,或使用吉特:git clone https://github.com/spring-guides/gs-contract-rest.git
  • 光盘成gs-contract-rest/initial
  • 跳转到创建合同生产者服务.

完成后,您可以根据 中的代码检查结果。​​gs-contract-rest/complete​

使用 Gradle 构建

使用 Maven 构建

使用 IDE 进行构建

创建合同生产者服务

首先需要创建生成协定的服务。这是一个常规的 Spring 启动应用程序,提供了一个非常简单的 REST 服务。其余服务仅返回 JSON 格式的对象。​​Person​

​contract-rest-service/src/main/java/hello/ContractRestServiceApplication.java​

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ContractRestServiceApplication {

public static void main(String[] args) {
SpringApplication.run(ContractRestServiceApplication.class, args);
}
}

创建 REST 服务的协定

REST 服务的协定可以定义为脚本。该合约指定,如果有对url的请求,示例数据,并且表示实体将在内容类型的响应正文中返回。​​.groovy​​​​GET​​​​/person/1​​​​id=1​​​​name=foo​​​​surname=bee​​​​Person​​​​application/json​

​contract-rest-service/src/test/resources/contracts/hello/find_person_by_id.groovy​

import org.springframework.cloud.contract.spec.Contract

Contract.make {
description "should return person by id=1"

request {
url "/person/1"
method GET()
}

response {
status OK()
headers {
contentType applicationJson()
}
body (
id: 1,
name: "foo",
surname: "bee"
)
}
}

在该阶段,将为 groovy 文件中指定的合约创建自动测试类。这是由 Gradle 或 Maven 中的构建插件分别完成的。自动生成的测试 java 类将扩展 .​​test​​​​org.springframework.cloud:spring-cloud-contract-gradle-plugin​​​​org.springframework.cloud:spring-cloud-contract-maven-plugin​​​​hello.BaseClass​

要在 Maven 中包含插件,您需要添加以下内容:

<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<baseClassForTests>hello.BaseClass</baseClassForTests>
</configuration>
</plugin>

若要运行测试,还需要在测试范围中包含依赖项。​​org.springframework.cloud:spring-cloud-starter-contract-verifier​

最后,创建用于测试的基类:

​contract-rest-service/src/test/java/hello/BaseClass.java​

package hello;

import org.junit.jupiter.api.BeforeEach;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;

import io.restassured.module.mockmvc.RestAssuredMockMvc;

@SpringBootTest(classes = ContractRestServiceApplication.class)
public abstract class BaseClass {

@Autowired PersonRestController personRestController;

@MockBean PersonService personService;

@BeforeEach public void setup() {
RestAssuredMockMvc.standaloneSetup(personRestController);

Mockito.when(personService.findPersonById(1L))
.thenReturn(new Person(1L, "foo", "bee"));
}

}

在此步骤中,执行测试时,测试结果应为 GREEN 表示 REST 控制器与协定一致,并且您具有功能齐全的服务。

检查简单的人员查询业务逻辑

模型类​​Person.java​​ ​​contract-rest-service/src/main/java/hello/Person.java​

package hello;

class Person {

Person(Long id, String name, String surname) {
this.id = id;
this.name = name;
this.surname = surname;
}

private Long id;

private String name;

private String surname;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getSurname() {
return surname;
}

public void setSurname(String surname) {
this.surname = surname;
}
}

服务Bean,它只是在内存中填充几个Person实体,并在询问时返回该实体。​​PersonService.java​​​​contract-rest-service/src/main/java/hello/PersonService.java​

package hello;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Service;

@Service
class PersonService {

private final Map<Long, Person> personMap;

public PersonService() {
personMap = new HashMap<>();
personMap.put(1L, new Person(1L, "Richard", "Gere"));
personMap.put(2L, new Person(2L, "Emma", "Choplin"));
personMap.put(3L, new Person(3L, "Anna", "Carolina"));
}

Person findPersonById(Long id) {
return personMap.get(id);
}
}

RestController bean,当收到具有 id 的人的 REST 请求时调用 bean。​​PersonRestController.java​​​​PersonService​​​​contract-rest-service/src/main/java/hello/PersonRestController.java​

package hello;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
class PersonRestController {

private final PersonService personService;

public PersonRestController(PersonService personService) {
this.personService = personService;
}

@GetMapping("/person/{id}")
public Person findPersonById(@PathVariable("id") Long id) {
return personService.findPersonById(id);
}
}

测试合同-休息-服务应用程序

将类作为 Java 应用程序或 Spring 引导应用程序运行。服务应从端口 开始。​​ContractRestServiceApplication.java​​​​8000​

在浏览器中访问服务,等。​​http://localhost:8000/person/1​​​​http://localhost:8000/person/2​

创建合约使用者服务

准备好合约生产者服务后,现在我们需要创建使用所提供的合约的客户端应用程序。这是一个常规的 Spring 启动应用程序,提供了一个非常简单的 REST 服务。其余服务只是返回一条带有被查询人员姓名的消息,例如 .​​Hello Anna​

​contract-rest-client/src/main/java/hello/ContractRestClientApplication.java​

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class ContractRestClientApplication {

public static void main(String[] args) {
SpringApplication.run(ContractRestClientApplication.class, args);
}
}

@RestController
class MessageRestController {

private final RestTemplate restTemplate;

MessageRestController(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}

@RequestMapping("/message/{personId}")
String getMessage(@PathVariable("personId") Long personId) {
Person person = this.restTemplate.getForObject("http://localhost:8000/person/{personId}", Person.class, personId);
return "Hello " + person.getName();
}

}

创建协定测试

生产者提供的合同应作为简单的春季测试使用。

​contract-rest-client/src/test/java/hello/ContractRestClientApplicationTest.java​

package hello;

import org.assertj.core.api.BDDAssertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

@SpringBootTest
@AutoConfigureStubRunner(
ids = "com.example:contract-rest-service:0.0.1-SNAPSHOT:stubs:8100",
stubsMode = StubRunnerProperties.StubsMode.LOCAL
)
public class ContractRestClientApplicationTest {

@Test
public void get_person_from_service_contract() {
// given:
RestTemplate restTemplate = new RestTemplate();

// when:
ResponseEntity<Person> personResponseEntity = restTemplate.getForEntity("http://localhost:8100/person/1", Person.class);

// then:
BDDAssertions.then(personResponseEntity.getStatusCodeValue()).isEqualTo(200);
BDDAssertions.then(personResponseEntity.getBody().getId()).isEqualTo(1l);
BDDAssertions.then(personResponseEntity.getBody().getName()).isEqualTo("foo");
BDDAssertions.then(personResponseEntity.getBody().getSurname()).isEqualTo("bee");

}
}

此测试类将加载合约生产者服务的存根,并确保与服务的集成与协定一致。

如果消费者服务的测试和生产者的合同之间的通信有问题,测试将失败,在对生产进行新的更改之前,需要修复问题。

测试协定-休息-客户端应用程序

将类作为 Java 应用程序或 Spring 引导应用程序运行。服务应从端口 开始。​​ContractRestClientApplication.java​​​​9000​

在浏览器中访问服务,等。​​http://localhost:9000/message/1​​​​http://localhost:9000/message/2​

总结

祝贺!你刚刚使用Spring让你的REST服务声明他们的契约,消费者服务与这个契约保持一致。

标签:java,Spring,springframework,contract,存根,应用程序,org,import,id
From: https://blog.51cto.com/u_15326439/5968601

相关文章