Mocking
REST template
RESTful API
Java
Unit testing

How do I mock a REST template exchange?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When production code calls RestTemplate.exchange, a good test should avoid real network traffic while still proving that your client handles requests and responses correctly. In practice, there are two main strategies: mock RestTemplate directly with Mockito, or keep a real RestTemplate and attach MockRestServiceServer to it.

Strategy 1: Mock RestTemplate With Mockito

If your class receives RestTemplate through constructor injection, Mockito is usually the fastest option. You stub the exchange call and return a controlled ResponseEntity.

Here is a simple client:

java
1import org.springframework.http.HttpEntity;
2import org.springframework.http.HttpHeaders;
3import org.springframework.http.HttpMethod;
4import org.springframework.http.ResponseEntity;
5import org.springframework.web.client.RestTemplate;
6
7public class UserClient {
8    private final RestTemplate restTemplate;
9
10    public UserClient(RestTemplate restTemplate) {
11        this.restTemplate = restTemplate;
12    }
13
14    public String fetchUserName(long id) {
15        HttpHeaders headers = new HttpHeaders();
16        HttpEntity<Void> request = new HttpEntity<>(headers);
17
18        ResponseEntity<String> response = restTemplate.exchange(
19            "https://api.example.com/users/" + id,
20            HttpMethod.GET,
21            request,
22            String.class
23        );
24
25        return response.getBody();
26    }
27}

And the corresponding unit test:

java
1import static org.junit.jupiter.api.Assertions.assertEquals;
2import static org.mockito.ArgumentMatchers.any;
3import static org.mockito.ArgumentMatchers.eq;
4import static org.mockito.Mockito.when;
5
6import org.junit.jupiter.api.Test;
7import org.mockito.Mockito;
8import org.springframework.http.HttpMethod;
9import org.springframework.http.HttpStatus;
10import org.springframework.http.ResponseEntity;
11import org.springframework.web.client.RestTemplate;
12
13class UserClientTest {
14    @Test
15    void fetchUserName_returnsBody() {
16        RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
17        UserClient client = new UserClient(restTemplate);
18
19        when(restTemplate.exchange(
20            eq("https://api.example.com/users/42"),
21            eq(HttpMethod.GET),
22            any(),
23            eq(String.class)
24        )).thenReturn(new ResponseEntity<>("Ava", HttpStatus.OK));
25
26        assertEquals("Ava", client.fetchUserName(42));
27    }
28}

This style is ideal when the test cares mainly about your client logic rather than the internals of RestTemplate itself.

Strategy 2: Use MockRestServiceServer

If you want to verify the actual request URL, HTTP method, and response handling against a real RestTemplate, MockRestServiceServer is usually the better tool.

java
1import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
2import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
3import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
4
5import org.junit.jupiter.api.Test;
6import org.springframework.http.HttpMethod;
7import org.springframework.http.MediaType;
8import org.springframework.test.web.client.MockRestServiceServer;
9import org.springframework.web.client.RestTemplate;
10
11class UserClientServerTest {
12    @Test
13    void fetchUserName_usesExpectedRequest() {
14        RestTemplate restTemplate = new RestTemplate();
15        MockRestServiceServer server = MockRestServiceServer.createServer(restTemplate);
16        UserClient client = new UserClient(restTemplate);
17
18        server.expect(requestTo("https://api.example.com/users/42"))
19            .andExpect(method(HttpMethod.GET))
20            .andRespond(withSuccess("Ava", MediaType.TEXT_PLAIN));
21
22        String result = client.fetchUserName(42);
23        server.verify();
24
25        org.junit.jupiter.api.Assertions.assertEquals("Ava", result);
26    }
27}

This approach stays closer to real HTTP client behavior without leaving the JVM.

Why Dependency Injection Matters

Mocking is much easier when RestTemplate is injected into the class under test. If the class creates new RestTemplate() internally, the test has to work much harder to control behavior.

That is why a client like this is easier to test and maintain:

java
public UserClient(RestTemplate restTemplate) {
    this.restTemplate = restTemplate;
}

Good testability often starts with small constructor design decisions.

Watch the Exact exchange Overload

exchange has several overloads. Your stub or mock-server expectation must match the one used by production code. This becomes especially important when the code uses:

  • 'ParameterizedTypeReference,'
  • URI templates with variables,
  • custom request entities,
  • generic response bodies.

A mock that targets the wrong overload can look correct and still never be called.

Which Tool Should You Choose?

Use Mockito when you want a narrow unit test of your class behavior. Use MockRestServiceServer when request construction itself is part of what you want to validate.

Neither approach is universally better. They answer slightly different testing questions.

Common Pitfalls

A common mistake is mocking one exchange overload while the real code calls another. That produces confusing tests that either fail unexpectedly or pass for the wrong reason.

Another issue is instantiating RestTemplate directly inside the class under test. That makes the code harder to isolate and often encourages weaker tests.

Teams also forget server.verify() when using MockRestServiceServer, which means the test may not actually assert that the expected HTTP interaction occurred.

Summary

  • 'RestTemplate.exchange can be tested either by mocking RestTemplate or by using MockRestServiceServer.'
  • Mockito is best for narrow unit tests focused on service logic.
  • 'MockRestServiceServer is better when request details should be validated.'
  • Constructor injection makes HTTP clients much easier to test.
  • Always match the exact exchange overload used by the production code.

Course illustration
Course illustration

All Rights Reserved.