Quick Guide to @RestClientTest in Spring Boot

1. Introduction

This article is a quick introduction to the @RestClientTest annotation.

The new annotation helps simplify and speed up the testing of REST clients in your Spring applications.

2. REST Client Support in Spring Boot Pre-1.4

Spring Boot is a handy framework that provides many auto-configured Spring beans with typical settings that allow you to concentrate less on configuration of a Spring application and more on your code and business logic.

But in version 1.3 we don’t get a lot of help when we want to create or test REST services clients. Its support for REST clients is not very deep.

To create a client for a REST API – a RestTemplate instance is typically used. Usually it has to be configured before usage and its configuration may vary, so Spring Boot does not provide any universally configured RestTemplate bean.

Same goes for testing REST clients. Before Spring Boot 1.4.0, the procedure of testing a Spring REST client was not very different than in any other Spring-based application. You would create a MockRestServiceServer instance, bind it to RestTemplate instance under test and provide it with mock responses to requests, like this:

RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer =
  MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(requestTo("/greeting"))
  .andRespond(withSuccess());

// Test code that uses the above RestTemplate ...

mockServer.verify();

You would also have to initialize the Spring container and make sure that only the needed components are loaded into the context, to speed up the context load time (and consequently, the test execution time).

3. New REST Client Features in Spring Boot 1.4+

In Spring Boot 1.4, the team has made a solid effort to simplify and speed up the creation and testing of REST clients.

So, let’s check out the new features.

3.1. Adding Spring Boot to Your Project

First, you’ll need to make sure your project is using Spring Boot 1.4.x or higher:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Newest release versions can be found here.

3.2. RestTemplateBuilder

Spring Boot brings both the auto-configured RestTemplateBuilder to simplify creating RestTemplates, and the matching @RestClientTest annotation to test the clients built with RestTemplateBuilder. Here’s how you can create a simple REST client with RestTemplateBuilder auto-injected for you:

@Service
public class DetailsServiceClient {

    private final RestTemplate restTemplate;

    public DetailsServiceClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder.build();
    }

    public Details getUserDetails(String name) {
        return restTemplate.getForObject("/{name}/details",
          Details.class, name);
    }
}

Notice that we did not explicitly wire the RestTemplateBuilder instance to a constructor. This is possible thanks to a new Spring feature called implicit constructor injection, which is discussed in this article.

RestTemplateBuilder provides convenience methods for registering message converters, error handlers, URI template handlers, basic authorization and also use any additional customizers that you need.

3.3. @RestClientTest

For testing such a REST client built with RestTemplateBuilder, you may use a SpringRunner-executed test class annotated with @RestClientTest. This annotation disables full auto-configuration and only applies configuration relevant to REST client tests, i.e. Jackson or GSON auto-configuration and @JsonComponent beans, but not regular @Component beans.

@RestClientTest ensures that Jackson and GSON support is auto-configured, and also adds pre-configured RestTemplateBuilder and MockRestServiceServer instances to the context. The bean under test is specified with value or components attribute of the @RestClientTest annotation:

@RunWith(SpringRunner.class)
@RestClientTest(DetailsServiceClient.class)
public class DetailsServiceClientTest {

    @Autowired
    private DetailsServiceClient client;

    @Autowired
    private MockRestServiceServer server;

    @Autowired
    private ObjectMapper objectMapper;

    @Before
    public void setUp() throws Exception {
        String detailsString = 
          objectMapper.writeValueAsString(new Details("John Smith", "john"));
        
        this.server.expect(requestTo("/john/details"))
          .andRespond(withSuccess(detailsString, MediaType.APPLICATION_JSON));
    }

    @Test
    public void whenCallingGetUserDetails_thenClientMakesCorrectCall() 
      throws Exception {

        Details details = this.client.getUserDetails("john");

        assertThat(details.getLogin()).isEqualTo("john");
        assertThat(details.getName()).isEqualTo("John Smith");
    }
}

Firstly, we need to ensure that this test is run with SpringRunner by adding the @RunWith(SpringRunner.class) annotation.

So, what’s new?

First – the @RestClientTest annotation allows us to specify the exact service under test – in our case it is the DetailsServiceClient class. This service will be loaded into the test context, while everything else is filtered out.

This allows us to autowire the DetailsServiceClient instance inside our test and leave everything else outside, which speeds up the loading of the context.

Second – as the MockRestServiceServer instance is also configured for a @RestClientTest-annotated test (and bound to the DetailsServiceClient instance for us), we can simply inject it and use.

Finally – JSON support for @RestClientTest allows us to inject the Jackson’s ObjectMapper instance to prepare the MockRestServiceServer’s mock answer value.

All that is left to do is to execute the call to our service and verify the results.

4. Conclusion

In this article we’ve discussed the new @RestClientTest annotation that allows easy and quick testing of REST clients built with Spring.

The source code for the article is available on GitHub.

Related posts:

Java Program to Implement Coppersmith Freivald’s Algorithm
Java program to Implement Tree Set
Lấy ngày giờ hiện tại trong Java
REST Pagination in Spring
Lập trình đa luồng trong Java (Java Multi-threading)
Lớp Properties trong java
Sử dụng CountDownLatch trong Java
Java Program to Repeatedly Search the Same Text (such as Bible by building a Data Structure)
Java Program to Find the Number of Ways to Write a Number as the Sum of Numbers Smaller than Itself
Versioning a REST API
A Custom Data Binder in Spring MVC
Hướng dẫn Java Design Pattern – Observer
Static Content in Spring WebFlux
A Guide to ConcurrentMap
Simple Single Sign-On with Spring Security OAuth2
Java Program to Find the Shortest Path from Source Vertex to All Other Vertices in Linear Time
Java Program to Check Cycle in a Graph using Topological Sort
Consuming RESTful Web Services
Custom Thread Pools In Java 8 Parallel Streams
Java Program to Implement Adjacency List
Spring Security Form Login
Làm thế nào tạo instance của một class mà không gọi từ khóa new?
Hướng dẫn Java Design Pattern – Proxy
Java Program to Check Whether it is Weakly Connected or Strongly Connected for a Directed Graph
Using a Spring Cloud App Starter
Vòng lặp for, while, do-while trong Java
Tính đa hình (Polymorphism) trong Java
OAuth2.0 and Dynamic Client Registration
HttpAsyncClient Tutorial
Converting Between a List and a Set in Java
Java Program to Construct an Expression Tree for an Prefix Expression
Using a Custom Spring MVC’s Handler Interceptor to Manage Sessions