Een inleiding tot Spring Cloud-contract

1. Inleiding

Spring Cloud Contract is een project dat ons, simpel gezegd, helpt bij het schrijven van Consumer-Driven Contracts (CDC).

Dit verzekert het contract tussen a Producent en een Klant, in een gedistribueerd systeem - voor zowel HTTP-gebaseerde als berichtgebaseerde interacties.

In dit korte artikel onderzoeken we het schrijven van testcases aan producenten en consumenten voor Spring Cloud Contract via een HTTP-interactie.

2. Producent - serverzijde

We gaan een CDC aan de producerzijde schrijven, in de vorm van een EvenOddController - wat alleen vertelt of de aantal parameter is even of oneven:

@RestController openbare klasse EvenOddController {@GetMapping ("/ validate / priemgetal") openbare String isNumberPrime (@RequestParam ("getal") Geheel getal) {return Integer.parseInt (getal)% 2 == 0? "Even": "Odd"; }}

2.1. Afhankelijkheden van Maven

Voor onze producentenkant hebben we de spring-cloud-starter-contract-verifier afhankelijkheid:

 org.springframework.cloud spring-cloud-starter-contract-verifier 2.1.1.RELEASE-test 

En we zullen moeten configureren spring-cloud-contract-maven-plugin met de naam van onze basistestklasse, die we in de volgende sectie zullen beschrijven:

 org.springframework.cloud spring-cloud-contract-maven-plugin 2.1.1.RELEASE true com.baeldung.spring.cloud.springcloudcontractproducer.BaseTestClass 

2.2. Producer Side Setup

We moeten een basisklasse toevoegen aan het testpakket die onze Spring-context laadt:

@RunWith (SpringRunner.class) @SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.MOCK) @DirtiesContext @AutoConfigureMessageVerifier openbare klasse BaseTestClass {@Autowired privé EvenOddController evenOddController; @Before public void setup () {StandaloneMockMvcBuilder standaloneMockMvcBuilder = MockMvcBuilders.standaloneSetup (evenOddController); RestAssuredMockMvc.standaloneSetup (standaloneMockMvcBuilder); }}

In de / src / test / resources / contracts / pakket, zullen we de teststubs toevoegen, zoals deze in het bestand shouldReturnEvenWhenRequestParamIsEven.groovy:

import org.springframework.cloud.contract.spec.Contract Contract.make {description "zou moeten terugkeren, zelfs als de nummerinvoer zelfs" request {method GET () url ("/ validate / prime-number") {queryParameters {parameter (" number "," 2 ")}}} antwoord {body (" Even ") status 200}} 

Als we de build uitvoeren, de plug-in genereert automatisch een testklasse met de naam ContractVerifierTest dat breidt onze BaseTestClass en stopt het erin / target / gegenereerde-test-bronnen / contracten /.

De namen van de testmethoden zijn afgeleid van het voorvoegsel "validate_ ” aaneengeschakeld met de namen van onze Groovy-teststubs. Voor het bovenstaande Groovy-bestand is de gegenereerde naam van de methode "Validate_shouldReturnEvenWhenRequestParamIsEven".

Laten we eens kijken naar deze automatisch gegenereerde testklasse:

openbare klasse ContractVerifierTest breidt BaseTestClass uit {@Test openbare ongeldige validate_shouldReturnEvenWhenRequestParamIsEven () gooit Uitzondering {// gegeven: MockMvcRequestSpecification-verzoek = gegeven (); // when: ResponseOptions response = given (). spec (request) .queryParam ("number", "2") .get ("/ validate / prime-number"); // then: assertThat (response.statusCode ()). isEqualTo (200); // en: String responseBody = response.getBody (). asString (); assertThat (responseBody) .isEqualTo ("Even"); } 

De build zal ook de stub-jar toevoegen aan onze lokale Maven-repository, zodat deze door onze consument kan worden gebruikt.

Stubs zullen aanwezig zijn in de uitvoermap onder stubs / mapping /.

3. Consument - Klantzijde

De consumentenkant van onze CDC zal stubs consumeren die door de producentenkant zijn gegenereerd via HTTP-interactie om het contract te behouden, dus elke verandering aan de kant van de producent zou het contract verbreken.

We zullen toevoegen BasicMathController, die een HTTP-verzoek zal doen om het antwoord van de gegenereerde stubs te krijgen:

@RestController openbare klasse BasicMathController {@Autowired privé RestTemplate restTemplate; @GetMapping ("/ bereken") public String checkOddAndEven (@RequestParam ("number") Geheel getal) {HttpHeaders httpHeaders = nieuwe HttpHeaders (); httpHeaders.add ("Content-Type", "application / json"); ResponseEntity responseEntity = restTemplate.exchange ("// localhost: 8090 / validate / priemgetal? Number =" + nummer, HttpMethod.GET, nieuwe HttpEntity (httpHeaders), String.class); return responseEntity.getBody (); }}

3.1. De Maven-afhankelijkheden

Voor onze consument moeten we de spring-cloud-contract-wiremock en spring-cloud-contract-stub-runner afhankelijkheden:

 org.springframework.cloud spring-cloud-contract-wiremock 2.1.1.RELEASE-test org.springframework.cloud spring-cloud-contract-stub-runner 2.1.1.RELEASE-test 

3.2. Instelling aan de kant van de consument

Nu is het tijd om onze stubrunner te configureren, die onze consument informeert over de beschikbare stubs in onze lokale Maven-repository:

@RunWith (SpringRunner.class) @SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.MOCK) @AutoConfigureMockMvc @AutoConfigureJsonTesters @AutoConfigureStubRunner (stubsMode = StubRunnerProperties. producer: +: stubs: 8090 ") openbare klasse BasicMathControllerIntegrationTest {@Autowired privé MockMvc mockMvc; @Test openbare leegte gegeven_WhenPassEvenNumberInQueryParam_ThenReturnEven () genereert uitzondering {mockMvc.perform (MockMvcRequestBuilders.get ("/ berekenen? Number = 2") .contentType (MediaType.APPLICATION_JSON)) .andExpect (status ()). IsOk () .string ("Even")); }}

Merk op dat de id's eigendom van de @AutoConfigureStubRunner annotatie specificeert:

  • com.baeldung.spring.cloud - de groupId van ons artefact
  • spring-cloud-contract-producer - de artefact-id van de producer stomppot
  • 8090 - de poort waarop de gegenereerde stubs zullen draaien

4. Wanneer het contract is verbroken

Als we wijzigingen aanbrengen aan de producentenkant die rechtstreeks van invloed zijn op het contract zonder de consumentenkant bij te werken, dit kan leiden tot contractfalen.

Stel dat we de EvenOddController verzoek URI aan / validate / change / priemgetal aan onze producentenkant.

Als we onze consument niet op de hoogte stellen van deze wijziging, stuurt de consument zijn verzoek alsnog naar de / validate / priemgetal URI, en de testcases aan de consumentenkant zullen gooien org.springframework.web.client.HttpClientErrorException: 404 niet gevonden.

5. Samenvatting

We hebben gezien hoe Spring Cloud Contract ons kan helpen bij het onderhouden van contracten tussen een serviceconsument en -producent, zodat we nieuwe code kunnen verspreiden zonder dat we ons zorgen hoeven te maken over het verbreken van de contracten.

En, zoals altijd, is de volledige implementatie van deze tutorial te vinden op GitHub.