Modern REST client testing with Spring Boot 4+ (replaces TestRestTemplate).
RestTestClient is the modern alternative to TestRestTemplate in Spring Boot 4.0+. It provides a fluent, reactive API for testing REST endpoints.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-restclient-test</artifactId>
<scope>test</scope>
</dependency>@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class OrderIntegrationTest {
@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);
assertThat(order.getStatus()).isEqualTo("PENDING");
});
}@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);
}@Test
void shouldUpdateOrder() {
restClient
.put()
.uri("/orders/1")
.body(new OrderUpdate("COMPLETED"))
.exchange()
.expectStatus()
.isOk();
}@Test
void shouldDeleteOrder() {
restClient
.delete()
.uri("/orders/1")
.exchange()
.expectStatus()
.isNoContent();
}restClient
.get()
.uri("/orders/1")
.exchange()
.expectStatus()
.isOk() // 200
.isCreated() // 201
.isNoContent() // 204
.isBadRequest() // 400
.isNotFound() // 404
.is5xxServerError() // 5xx
.isEqualTo(200); // Specific coderestClient
.post()
.uri("/orders")
.exchange()
.expectHeader()
.location("/orders/1")
.contentType(MediaType.APPLICATION_JSON)
.exists("X-Request-Id")
.valueEquals("X-Api-Version", "v1");restClient
.get()
.uri("/orders/1")
.exchange()
.expectBody(Order.class)
.value(order -> assertThat(order.getId()).isEqualTo(1L))
.returnResult();restClient
.get()
.uri("/orders")
.exchange()
.expectBody()
.jsonPath("$.content[0].id").isEqualTo(1)
.jsonPath("$.content[0].status").isEqualTo("PENDING")
.jsonPath("$.totalElements").isNumber();restClient
.get()
.uri("/orders/1")
.header("Authorization", "Bearer token")
.header("X-Api-Key", "secret")
.exchange();restClient
.get()
.uri(uriBuilder -> uriBuilder
.path("/orders")
.queryParam("status", "PENDING")
.queryParam("page", 0)
.queryParam("size", 10)
.build())
.exchange();restClient
.get()
.uri("/orders/{id}", 1L)
.exchange();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();
}
}| 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 |
@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);
}@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));
}- 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