Contract testing with Spring Cloud Contract (Part 2)

// UserController.java
@RestController
@RequestMapping("/users")
public class UserController {

@GetMapping("/{userId}")
public User getMe(@PathVariable Integer userId) {
return User.builder()
.id(userId)
.firstName("John")
.lastName("Doe")
.email("john.doe@gmail.com")
.build();
}
}
// User.java
@Value
@Builder
public class User {

Integer id;
String firstName;
String lastName;
String email;
}
<dependencies>
<
dependency>
<
groupId>org.springframework.cloud</groupId>
<
artifactId>spring-cloud-starter-contract-verifier</artifactId>
<
version>2.2.4.RELEASE</version>
<
scope>test</scope>
</
dependency>
</
dependencies>

<
build>
<
plugins>
<
plugin>
<
groupId>org.springframework.cloud</groupId>
<
artifactId>spring-cloud-contract-maven-plugin</artifactId>
<
extensions>true</extensions>
<
version>2.2.4.RELEASE</version>
<
configuration>
<
baseClassForTests>
me.alexthered.contracttesting.producer.controller.IntegrationTestBase
</baseClassForTests>
<
testFramework>JUNIT5</testFramework>
</
configuration>
</
plugin>
<
plugin>
<
groupId>org.springframework.boot</groupId>
<
artifactId>spring-boot-maven-plugin</artifactId>
</
plugin>
</
plugins>
</
build>
// find_user_by_id.groovy
import org.springframework.cloud.contract.spec.Contract

Contract.make {
description "should return correct user by id=1000"

request {
url "/users/1000"
method GET()
}

response {
status OK()
headers {
contentType applicationJson()
}
body(
id: 1000,
firstName: "John",
lastName: "Doe",
email: "john.doe@gmail.com"
)
}
}
package me.alexthered.contracttesting.producer.controller;

import me.alexthered.contracttesting.producer.controller.IntegrationTestBase;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;
import io.restassured.response.ResponseOptions;

import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat;
import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*;
import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;
import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;

@SuppressWarnings("rawtypes")
public class UsersTest extends IntegrationTestBase {

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


// when:
ResponseOptions response = given().spec(request)
.get("/users/1000");

// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).matches("application/json.*");

// and:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field("['id']").isEqualTo(1000);
assertThatJson(parsedJson).field("['firstName']").isEqualTo("John");
assertThatJson(parsedJson).field("['lastName']").isEqualTo("Doe");
assertThatJson(parsedJson).field("['email']").isEqualTo("john.doe@gmail.com");
}

}
<dependencies>
<
dependency>
<
groupId>org.springframework.cloud</groupId>
<
artifactId>spring-cloud-contract-wiremock</artifactId>
<
version>2.2.4.RELEASE</version>
<
scope>test</scope>
</
dependency>
<
dependency>
<
groupId>org.springframework.cloud</groupId>
<
artifactId>spring-cloud-contract-stub-runner</artifactId>
<
version>2.2.4.RELEASE</version>
<
scope>test</scope>
</
dependency>
</
dependencies>
@RestController
public class HelloController {

public static final String FIRST_NAME = "firstName";
private final RestTemplate restTemplate;

@Value("${producer.url}")
private String producerUrl;

public HelloController() {
this.restTemplate = new RestTemplateBuilder()
.build();
}

@GetMapping("/hello/{userId}")
public String helloUser(@PathVariable Integer userId) {
return "Hello " + getUserFirstName(userId);
}

private String getUserFirstName(Integer userId) {
Map<String, String> responseEntity = restTemplate.getForObject(
producerUrl + "/users/{userId}",
Map.class,
userId);

return responseEntity.get(FIRST_NAME);
}
}
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureStubRunner(
stubsMode = StubRunnerProperties.StubsMode.LOCAL,
ids = "me.alexthered.contract-testing:producer:+:stubs:8080"
)
public class HelloControllerTest {

@LocalServerPort
private int port;

@Autowired
private TestRestTemplate restTemplate;

@Test
void should_get_hello_string_correctly() {
assertThat(
this.restTemplate.getForObject("http://localhost:" + port + "/hello/1000", String.class))
.isEqualTo("Hello John");
}

}
@AutoConfigureStubRunner(
stubsMode = StubRunnerProperties.StubsMode.LOCAL,
ids = "me.alexthered.contract-testing:producer:+:stubs:8080"
)

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store