mirror of
https://github.com/github/awesome-copilot.git
synced 2026-03-20 08:05:12 +00:00
- Introduced MockMvcTester for AssertJ-style assertions in Spring MVC testing. - Added @RestClientTest for testing REST clients with MockRestServiceServer. - Implemented RestTestClient as a modern alternative to TestRestTemplate. - Documented migration steps from Spring Boot 3.x to 4.0, including dependency and annotation changes. - Created an overview of test slices to guide testing strategies. - Included Testcontainers setup for JDBC testing with PostgreSQL and MySQL. - Enhanced @WebMvcTest documentation with examples for various HTTP methods and validation.
4.9 KiB
4.9 KiB
RestTestClient
Modern REST client testing with Spring Boot 4+ (replaces TestRestTemplate).
Overview
RestTestClient is the modern alternative to TestRestTemplate in Spring Boot 4.0+. It provides a fluent, reactive API for testing REST endpoints.
Setup
Dependency (Spring Boot 4+)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-restclient-test</artifactId>
<scope>test</scope>
</dependency>
Basic Configuration
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class OrderIntegrationTest {
@Autowired
private RestTestClient restClient;
}
HTTP Methods
GET Request
@Test
void shouldGetOrder() {
restClient
.get()
.uri("/orders/1")
.exchange()
.expectStatus()
.isOk()
.expectBody(Order.class)
.value(order -> {
assertThat(order.getId()).isEqualTo(1L);
assertThat(order.getStatus()).isEqualTo("PENDING");
});
}
POST Request
@Test
void shouldCreateOrder() {
OrderRequest request = new OrderRequest("Laptop", 2);
restClient
.post()
.uri("/orders")
.contentType(MediaType.APPLICATION_JSON)
.body(request)
.exchange()
.expectStatus()
.isCreated()
.expectHeader()
.location("/orders/1")
.expectBody(Long.class)
.isEqualTo(1L);
}
PUT Request
@Test
void shouldUpdateOrder() {
restClient
.put()
.uri("/orders/1")
.body(new OrderUpdate("COMPLETED"))
.exchange()
.expectStatus()
.isOk();
}
DELETE Request
@Test
void shouldDeleteOrder() {
restClient
.delete()
.uri("/orders/1")
.exchange()
.expectStatus()
.isNoContent();
}
Response Assertions
Status Codes
restClient
.get()
.uri("/orders/1")
.exchange()
.expectStatus()
.isOk() // 200
.isCreated() // 201
.isNoContent() // 204
.isBadRequest() // 400
.isNotFound() // 404
.is5xxServerError() // 5xx
.isEqualTo(200); // Specific code
Headers
restClient
.post()
.uri("/orders")
.exchange()
.expectHeader()
.location("/orders/1")
.contentType(MediaType.APPLICATION_JSON)
.exists("X-Request-Id")
.valueEquals("X-Api-Version", "v1");
Body Assertions
restClient
.get()
.uri("/orders/1")
.exchange()
.expectBody(Order.class)
.value(order -> assertThat(order.getId()).isEqualTo(1L))
.returnResult();
JSON Path
restClient
.get()
.uri("/orders")
.exchange()
.expectBody()
.jsonPath("$.content[0].id").isEqualTo(1)
.jsonPath("$.content[0].status").isEqualTo("PENDING")
.jsonPath("$.totalElements").isNumber();
Request Configuration
Headers
restClient
.get()
.uri("/orders/1")
.header("Authorization", "Bearer token")
.header("X-Api-Key", "secret")
.exchange();
Query Parameters
restClient
.get()
.uri(uriBuilder -> uriBuilder
.path("/orders")
.queryParam("status", "PENDING")
.queryParam("page", 0)
.queryParam("size", 10)
.build())
.exchange();
Path Variables
restClient
.get()
.uri("/orders/{id}", 1L)
.exchange();
With MockMvc
RestTestClient can also work with MockMvc (no server startup):
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestTestClient
class OrderMockMvcTest {
@Autowired
private RestTestClient restClient;
@Test
void shouldWorkWithMockMvc() {
// Uses MockMvc under the hood - no server startup
restClient
.get()
.uri("/orders/1")
.exchange()
.expectStatus()
.isOk();
}
}
Comparison: RestTestClient vs TestRestTemplate
| Feature | RestTestClient | TestRestTemplate |
|---|---|---|
| Style | Fluent/reactive | Imperative |
| Spring Boot | 4.0+ | All versions (deprecated in 4) |
| Assertions | Built-in | Manual |
| MockMvc support | Yes | No |
| Async | Native | Requires extra handling |
Migration from TestRestTemplate
Before (Deprecated)
@Autowired
private TestRestTemplate restTemplate;
@Test
void shouldGetOrder() {
ResponseEntity<Order> response = restTemplate
.getForEntity("/orders/1", Order.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody().getId()).isEqualTo(1L);
}
After (RestTestClient)
@Autowired
private RestTestClient restClient;
@Test
void shouldGetOrder() {
restClient
.get()
.uri("/orders/1")
.exchange()
.expectStatus()
.isOk()
.expectBody(Order.class)
.value(order -> assertThat(order.getId()).isEqualTo(1L));
}
Best Practices
- Use with @SpringBootTest(WebEnvironment.RANDOM_PORT) for real HTTP
- Use with @AutoConfigureMockMvc for faster tests without server
- Leverage fluent assertions for readability
- Test both success and error scenarios
- Verify headers for security/API versioning