Open In App

Mocking a RestTemplate in Spring

Last Updated : 23 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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.

  • Spring Boot framework
  • JUnit Testing
  • Testing in Spring framework
  • RestTemplate & Mockito
  • API functionality
  • Spring Stater project creation
  • Spring dependency Management

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:

  • Now, we created required classes in the main package of the project folder.
  • First, we created one domain class that is User in this class we declare some fields namely id,username, age and role.
  • Here, the role is enum type. We use some spring annotations @AllArgsConstructor, @NoArgsConstructor,@Data and @Document(collection = “userdata”) to handle data.
Java
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
}
  • Next, we created one enum class in that main package by using enum keyword that is Role.
  • Then we declare some roles in that enum role class.
  • The roles are ADMIN, USER, GUEST.


Step 5:

  • Now, we created one more java interface in that package that is UserRepository.
  • This repository is used for handling database operation like save, insert, delete and other database operations.
  • We created this repository by using @Repository @EnableMongoRepositories, and this repository takes two arguments as input those are domain class name and it’s ID datatype.
  • And we extends this UserRepository to MongoRepository.
  • Then, we created some user defines functions in this repository.
Java
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:

  • Now we created one more java class in main package with name UserServic,e and we use @Service spring annotation to create a service layer in the web application.
  • After this in java class we created some methods for save the user data, find all user data and findbyrole methods.
  • And the findByRoll is user define function that’s why we created a method in Repository interface.
Java
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:

  • After this, we created one more java class in the main package with name UserController and this class is used for creating API end points and handling HTTP requests.
  • And we access service layer methods from this controller by using autowiring the UserService class.
  • Then we define three different API end points namely save which is POST type, getAll API which is GET mapping and byRole API which GET mapping.
  • These APIs are used for save user data, retrieve all user data and find users by their role.
Java
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:

  • Now, develop logic in test package for testing the application performance.
  • And write test cases, here, we have used @SpringBootTest, @ExtendWith(MockitoExtension.class).
  • After this, we created mock objects for RestTemplate.
  • After this, we created Mock Bean for UserService, then we Autowired the UserController.
  • After this we created one test case by using @Test annotation and run this project as JUnit then observe object.
Java
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




Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads