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:

Flattening Nested Collections in Java
Java Program to Implement Disjoint Sets
Java Program to Implement Self Balancing Binary Search Tree
Java Program to Perform Encoding of a Message Using Matrix Multiplication
Giới thiệu Json Web Token (JWT)
Array to String Conversions
Java Program to Check Cycle in a Graph using Topological Sort
Java Program to Create a Minimal Set of All Edges Whose Addition will Convert it to a Strongly Conne...
Hướng dẫn sử dụng Java Annotation
Java Program to Implement Flood Fill Algorithm
JUnit5 Programmatic Extension Registration with @RegisterExtension
Java Program to Emulate N Dice Roller
Quick Guide to the Java StringTokenizer
Disable Spring Data Auto Configuration
How to Use if/else Logic in Java 8 Streams
Request Method Not Supported (405) in Spring
Java Program to Implement Double Order Traversal of a Binary Tree
Working with Tree Model Nodes in Jackson
Java Program to Implement AA Tree
Java Program to Create the Prufer Code for a Tree
Hướng dẫn Java Design Pattern – Chain of Responsibility
The Difference Between Collection.stream().forEach() and Collection.forEach()
OAuth 2.0 Resource Server With Spring Security 5
RestTemplate Post Request with JSON
An Example of Load Balancing with Zuul and Eureka
A Guide to Queries in Spring Data MongoDB
Hướng dẫn Java Design Pattern – Visitor
Mockito and JUnit 5 – Using ExtendWith
Hướng dẫn Java Design Pattern – Interpreter
Hướng dẫn Java Design Pattern – Command
Java – InputStream to Reader
Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java