Open In App

Mocking a RestTemplate in Spring

The Spring Boot framework provides many features for testing purposes also a lot of Spring annotations are available for testing the Application performance. The Spring is a common practice for testing applications that make HTTP requests without hitting the network. This helps in isolating your tests and makes them faster and more reliable. In Spring Framework we can achieve this by using frameworks like Mockito and Spring Boot's testing utilities. This article uses Mockito, and RestTemplate tools to test the Spring Application.

Now we will explain about Mocking Rest Template in the Spring Boot framework, Here we created one sample Spring Boot Project then we will write test cases by using RestTemplate to test the Spring Boot Application performance.

Mocking

Mocking is a technique used in Software Development mostly in the context of Testing. To create objects that simulate the behavior of real objects. These simulated objects are known as Mocks. Also Mocking is often used to isolate the code being tested from its dependencies such as databases, web services, and other components.

And The Mocking supports lot of features those are Isolation, Controlled Behavior, State Verification, Speed and Isolation, Test-Driven Development and other features.

RestTemplate

The RestTemplate is a class which is provided by the Spring Boot Framework and it specifies the process of making HTTP requests to RESTful web service or APIs. And it is part of Spring Web Module and provides high level abstraction for interacting with HTTP based services compared to using raw HTTP Clients.

This RestTemplate can support HTTP Methods like POST, PUT, PATCH, GET, DELETE, Request, and Response Handling, URL Template Expansion, Message Converters means convert HTTP request and response bodies to and from Java objects, Error Handling and Customization and Extensibility.

Prerequisites:

To understand this article, we should have proper knowledge on below listed topics then only this article become easy to understand.

Project Folder Structure:


Project Folder Structure


Steps to Mocking a RestTemplate in Spring

To Mocking a RestTemplate in Spring, first we need create a Spring Boot project. And also to achieve Mocking a RestTemplate in Spring we need follow the below steps.

Step 1:

Create a Spring Boot project by using Spring initializer with required project dependencies. Below we provide dependencies what we use for this Project.

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}


Step 2:

Once project is successfully created, then configure the mongo db connection by using database name, port number and host name.

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=work


Step 3:

package com.app;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Document(collection = "userdata")
public class User {
    @Id
    private String id;
    private String username;
    private String age;
    private Role role;
}


Step 4:

package com.app;

public enum Role {
ADMIN, USER, GUEST
}


Step 5:

package com.app;

import java.util.List;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.stereotype.Repository;

@Repository
@EnableMongoRepositories
public interface UserRepository extends MongoRepository<User, String> {

    List<User> findByRole(Role role);

}


Step 6:

package com.app;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    // save user data
    public User createUser(User user) {
        return userRepository.save(user);
    }
    
    // get all users data
    public List<User> findAllUsers() {
        return userRepository.findAll();
    }
    
    // find by role 
    public List<User> findUsersByRole(Role role) {
        return userRepository.findByRole(role);
    }
}


Step 7:

package com.app;

import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RestTemplate restTemplate;

    // Endpoint to handle POST requests to "/save"
    @PostMapping("/save")
    public ResponseEntity<User> createUser(@RequestBody User user) {
        // Create a new user
        User createdUser = userService.createUser(user);
        // Return a response with the created user and HTTP status code 201 (Created)
        return new ResponseEntity<>(createdUser, HttpStatus.CREATED);
    }

    // Endpoint to handle GET requests to "/getAll"
    @GetMapping("/getAll")
    public ResponseEntity<List<User>> getAllUsers() {
        // Retrieve all users
        List<User> users = userService.findAllUsers();
        // Return a response with the list of users and HTTP status code 200 (OK)
        return ResponseEntity.ok(users);
    }

    // Endpoint to handle GET requests to "/byRole"
    @GetMapping("/byRole")
    public ResponseEntity<List<User>> findUsersByRole(@RequestParam("role") Role role) {
        // Construct API URL based on role parameter
        String apiUrl = "http://localhost:8080/byRole?role=" + role;
        // Make GET request to the specified API URL and retrieve users with the specified role
        User[] usersArray = restTemplate.getForObject(apiUrl, User[].class);
        // Convert array of users to a list
        List<User> users = Arrays.asList(usersArray);
        // Return a response with the list of users and HTTP status code 200 (OK)
        return ResponseEntity.ok(users);
    }
}


Step 8:

Once entire logic is developed, then run this project as Spring Boot application and this project will run on server port number 8080.

Project Running


Step 9:

package com.app;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

@ExtendWith(MockitoExtension.class)
@SpringBootTest
public class EnumMappingApplicationTests {

    @Mock
    private RestTemplate restTemplateMock;

    @MockBean
    private UserService userServiceMock;

    @Autowired
    private UserController userController;
    
    @Test
    public void testCreateUser_Success() {
        // Mock the behavior of UserService
        User user = new User("10", "John", "20", Role.ADMIN);
        when(userServiceMock.createUser(user)).thenReturn(user);

        // Call the controller method
        ResponseEntity<User> response = userController.createUser(user);

        // Verify the response
        assertEquals(HttpStatus.CREATED, response.getStatusCode());
        assertEquals(user, response.getBody());
    }

    @Test
    public void testGetAllUsers_Success() {
        // Mock the behavior of UserService
        User user1 = new User("10", "John", "20", Role.ADMIN);
        User user2 = new User("20", "Alice", "30", Role.USER);
        List<User> users = Arrays.asList(user1, user2);
        when(userServiceMock.findAllUsers()).thenReturn(users);

        // Call the controller method
        ResponseEntity<List<User>> response = userController.getAllUsers();

        // Verify the response
        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertEquals(users, response.getBody());
    }
    
    @Test
    public void testFindUsersByRole() {
        // Mock the behavior of RestTemplate
        when(restTemplateMock.getForObject("http://localhost:8080/byRole?role=ADMIN", User[].class))
                .thenReturn(new User[]{new User("10", "John", "20", Role.ADMIN)});
        
        // Call the controller method
        ResponseEntity<List<User>> response = userController.findUsersByRole(Role.ADMIN);
        
        // Verify the response
        assertEquals(Collections.singletonList(new User("10", "John", "20", Role.ADMIN)), response.getBody());
    }
}


Output in Postman:

1. Create User API:

New role "Admin" created and the response of HTTP status code 201 (Created) generated for the created user object.

New role created


2. Get All API:

Here, it lists all the users with HTTP status code 200 (OK).

Get all Output


3. Find by Role API:

Here, it lists the users with specified role along with HTTP status code 200 (OK).

find by role Output


Article Tags :