Monday, September 22, 2025

Spring Boot Data JPA Repository Unit Test

In this article we'll see how to unit test JPA repositories and the persistence layer of an application in Spring Boot using the specialized annotation @DataJpaTest.

Required dependencies

First of all, ensure spring-boot-starter-test dependency is included. If you are using Maven then this dependency can be included in pom.xml like this.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

This starter bundles together common testing libraries like JUnit, Mockito, AssertJ, Spring Boot Test etc.

It is also suggested to use in-memory DB for unit testing the repository layer. This ensures that tests are self-contained and do not rely on an external database. @DataJpaTest annotation automatically configures an embedded database, if it is available on the classpath. So, it is also advisable to use H2 in-memory database, dependency for it is as given below.

<!-- H2 Database -->
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <scope>test</scope>
</dependency>

Benefits of @DataJpaTest annotation

  1. Fast testing- @DataJpaTest annotation disables the full auto-configuration of Spring Boot application. It only configures the components requires for persistence layer testing like Entity classes, data JPA repositories. It also injects a TestEntityManager bean, which provides an alternative to the standard JPA EntityManager that is specifically designed for tests. Other components like Controllers, Service classes are not configured.
  2. Transactional by default- By default, data JPA tests are transactional and roll back at the end of each test which ensures a clean database state for subsequent tests. You can disable this default behavior by using @Transactional annotation. It can be used at the class level.
    @DataJpaTest
    @Transactional(propagation = Propagation.NOT_SUPPORTED) 
    public class UserRepositoryTest(){
    
    }
    

    It can also be used at method level.

  3. Default logging- Logging of executed SQL queries is done by default. This can be controlled using the showSql attribute of the @DataJpaTest annotation.
    @DataJpaTest(showSql = false)
    public class UserRepositoryTest(){
    
    }
    
  4. Providing properties- By using properties attribute you can specify additional Spring Boot configuration properties directly within the @DataJpaTest annotation.
    @DataJpaTest(properties = {
        "spring.datasource.url=jdbc:h2:mem:testdb",
        "spring.jpa.properties.hibernate.show_sql=true"
    })
    public class UserRepositoryTest(){
    }
    
  5. Using real database- @DataJpaTest annotation also provides flexibility to run tests against a real database. You can use the @AutoConfigureTestDatabase annotation for that purpose.
    @DataJpaTest
    @AutoConfigureTestDatabase(replace = Replace.NONE)
    public class UserRepositoryTest(){
    }
    

Unit test for Spring Data JPA Repository using @DataJpaTest annotation

Please refer this post- Spring Boot + Data JPA + MySQL REST API CRUD Example to see the application for which we are going to write unit tests.

Entity class

The JPA entity class used for relational mapping is as given below.

User.java

import java.time.LocalDate;
import java.util.Objects;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;

@Entity
@Table(name="app_user")
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private int userId;
  
  @NotBlank(message = "First name is required")
  @Column(name="FIRST_NAME")
  private String firstName;
  
  @NotBlank(message = "Last name is required")
  @Column(name="LAST_NAME")
  private String lastName;
  @Column(name="USER_TYPE")
  private String userType;
  @Column(name="START_DATE")
  private LocalDate startDate;
    
  public int getUserId() {
    return userId;
  }
  public void setUserId(int userId) {
    this.userId = userId;
  }
  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public String getUserType() {
    return userType;
  }
  public void setUserType(String userType) {
    this.userType = userType;
  }
  public LocalDate getStartDate() {
    return startDate;
  }
  public void setStartDate(LocalDate startDate) {
    this.startDate = startDate;
  }
 // toString(), hashCode() and equals() methods  
}

Please note that giving table name as "User" may cause problem with H2 DB as it is a reserved keyword in H2 database. That is why table name is "app_user".

Data JPA repository

JPA repository interface is as given below.

UserRepository.java

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.netjstech.model.User;

public interface UserRepository extends JpaRepository<User, Integer>{
  List<User> findUserByUserType(String userType);
}

Dialect changes in application.yaml file

If you are using in-memory database H2 for testing then you may add dialect for the same in the application.yaml or application.properties file.

jpa:
    properties:
      hibernate:
        sqldialect: org.hibernate.dialect.H2Dialect

With these changes in the Spring Boot application, you can write tests for the data JPA repository. Here is the full test class with 6 unit tests for save, update, delete, getAll, getById and findUserByUserType().

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import com.netjstech.dao.UserRepository;
import com.netjstech.model.User;

@DataJpaTest
class UserRepositoryTest {
  
  @Autowired
  UserRepository userRepositroy;
  
  @Test
  void testSaveUser() {
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    
    User savedUser = userRepositroy.save(user);
        
    assertThat(savedUser).isNotNull();
    assertNotNull(savedUser.getUserId());
    assertEquals(savedUser.getFirstName(), user.getFirstName());
    
  }
  
  @Test
  void testGetAllUsers() {
    User user1 = new User();
    user1.setFirstName("Ram");
    user1.setLastName("Tiwari");
    user1.setUserType("Platinum");
    user1.setStartDate(LocalDate.of(2025, 8, 26));
    
    User user2 = new User();
    user2.setFirstName("Shyam");
    user2.setLastName("Sharma");
    user2.setUserType("Gold");
    user2.setStartDate(LocalDate.of(2025, 7, 22));
    
    userRepositroy.save(user1);
    userRepositroy.save(user2);
    
    List<User> users = userRepositroy.findAll();
    
    assertNotNull(users);
    assertThat(users.size()).isEqualTo(2);
  }
  
  @Test
  void testGetUserById() {
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    User savedUser = userRepositroy.save(user);
    
    Optional<User> userFetched = userRepositroy.findById(savedUser.getUserId());
    
    assertThat(userFetched).isNotEmpty();
    
    assertEquals(user.getLastName(), userFetched.get().getLastName());
  }
  
  @Test
  void testGetAllUsersByType() {
    User user1 = new User();
    user1.setFirstName("Ram");
    user1.setLastName("Tiwari");
    user1.setUserType("Platinum");
    user1.setStartDate(LocalDate.of(2025, 8, 26));
    
    User user2 = new User();
    user2.setFirstName("Shyam");
    user2.setLastName("Sharma");
    user2.setUserType("Gold");
    user2.setStartDate(LocalDate.of(2025, 7, 22));
    
    User user3 = new User();
    user3.setFirstName("Anita");
    user3.setLastName("Verma");
    user3.setUserType("Gold");
    user3.setStartDate(LocalDate.of(2025, 7, 20));
    
    userRepositroy.save(user1);
    userRepositroy.save(user2);
    userRepositroy.save(user3);
    
    String userType = "Gold";
    
    List<User> user = userRepositroy.findUserByUserType(userType);
    
    assertNotNull(user);
    assertEquals(user.size(), 2);
  }
  
  @Test
  void testUpdateUser() {
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    
    User savedUser = userRepositroy.save(user);
    
    User userDB = userRepositroy.findById(savedUser.getUserId()).get();
    //update property
    userDB.setUserType("Gold");
    // save again
    savedUser = userRepositroy.save(userDB);
    
    assertNotNull(savedUser);
    assertEquals(savedUser.getUserType(), "Gold");
                
  }
  
  @Test
  void testDeletUser() {
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    
    User savedUser = userRepositroy.save(user);
    
    userRepositroy.deleteById(savedUser.getUserId());
    
    Optional<User> userFetched = userRepositroy.findById(savedUser.getUserId());
    
    
    assertThat(userFetched).isEmpty();
  }
}

That's all for this topic Spring Boot Data JPA Repository Unit Test. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring Boot Unit Test For REST API
  2. Spring Boot + Spring Security JWT Authentication Example
  3. Spring Boot Spring Initializr
  4. Spring Boot Microservice - Service Registration and Discovery With Eureka
  5. @Conditional Annotation in Spring

You may also like-

  1. Spring depends-on Attribute and @DependsOn With Examples
  2. Spring NamedParameterJdbcTemplate Insert, Update And Delete Example
  3. Spring Transaction Management Example - @Transactional Annotation and JDBC
  4. Spring Batch Processing With List of Objects in batchUpdate() Method
  5. Controlled and Uncontrolled Components in React
  6. Greatest Common Divisor (GCD) of Two Numbers Java Program
  7. Multi-Catch Statement in Java Exception Handling
  8. Strings in Python With Method Examples

Greatest Common Divisor (GCD) of Two Numbers Java Program

In this post we'll see how to write a Java program to calculate the greatest common divisor (GCD) of two numbers. It is also known as the highest common factor (HCF).

GCD of two integers is the highest integer that can completely divide both the integers which means remainder is 0 for both of the integers. For example- GCD of 33 and 110 is 11 as that is the highest number which completely divides both numbers.

33 = [1, 3, 11]
110 = [1, 2, 5, 10, 11]

Java program to calculate GCD of two numbers can be written using following approaches-

  1. Writing the logic as per the explanation of calculating GCD. Find the highest number that completely divided both numbers by doing that in a loop.
  2. Using Euclid algorithm (Repeated subtraction logic)
  3. Using Euclid algorithm (Repeated division logic)

1. Finding highest common divisor using loop

In this approach you need to run the loop from 1 up to minimum of two numbers and keep dividing both the numbers with the current loop iteration value. If it completely divides both the numbers then store it. By the end of the loop you will have the GCD.

import java.util.Scanner;
public class GCDCompute {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    
    System.out.println("Enter first number");
    int a = sc.nextInt();
    
    System.out.println("Enter second number");
    int b = sc.nextInt();

    System.out.println(computeGCD(a, b));      
  }
  
  public static int computeGCD(int a, int b) {
    // edge case where one or both numbers are zero
    if (a == 0) {
        return b;
    }
    if (b == 0) {
        return a;
    }
    int gcd = 1;
    for(int i = 1; i <= a && i <= b; i++) {
      if(a%i == 0 && b%i==0) {
        // completely divides so store the i value
        gcd = i;
      }
    }
    return gcd;
  }
}

Output

Enter first number
112
Enter second number
30
GCD is 2
Enter first number
0
Enter second number
5
GCD is 5

2. Using Euclid algorithm (Repeated subtraction logic) - Java Program

Euclid algorithm is considered more efficient than the general approach shown above. The repeated subtraction variant of Euclid algorithm states that the GCD of two numbers remains same if the greatest of the two numbers is replaced by the difference of the two numbers. This process is repeatedly done until both of the numbers become equal. This number at the end is the GCD of the two given numbers.

For example, if the numbers are 36 and 16.

  1. Greater of the two is 36 so that is replaced by the difference of the two.
  2. So, now the numbers are 20 and 16 again process is repeated
  3. Numbers are now 16 and 4; again subtract 4 from 16 giving 12
  4. Numbers 12 and 4 give 8 and 4
  5. 8 and 4 give 4 and 4, since numbers are equal now so 4 is the GCD.
public class GCDCompute {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println("Enter first number");
    int a = sc.nextInt();
    
    System.out.println("Enter second number");
    int b = sc.nextInt();

    System.out.println("GCD is " + gcdEuclidSubtraction (a, b));
  }
  
  public static int gcdEuclidSubtraction(int a, int b) {
    // edge case where one or both numbers are zero
    if (a == 0) {
        return b;
    }
    if (b == 0) {
        return a;
    }
    while(a != b) {
      if(a > b) {
        a = a - b;
      }else {
        b = b - a;
      }
    }
    
    return a;
  }
}

Output

Enter first number
36
Enter second number
16
GCD is 4

3. Using Euclid algorithm (Repeated division logic) - Java Program

This variant of Euclid algorithm further optimizes it by using division rather than subtraction. It works as follows.

  1. Divide the greater of the two number by the second number.
  2. Assign second number to the first number and remainder to the second number.
  3. Repeat step 1 and 2 until the remainder is zero. The last non-zero remainder is the GCD.

For example, if the two numbers are 36 and 16 then-

  1. Divide 36 by 16 giving remainder as 4.
  2. Now 16 becomes the first number and 4 becomes the second number. Repeat the process of division giving remainder as 0.
  3. That last non-zero remainder 4 is the GCD.
public class GCDCompute {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println("Enter first number");
    int a = sc.nextInt();
    
    System.out.println("Enter second number");
    int b = sc.nextInt();

    System.out.println("GCD is " + gcdEuclidDivision(a, b));    
  }
  public static int gcdEuclidDivision(int a, int b) {
    int temp;
    // Find the maximum of two numbers, which is assigned to variable a
    if(a < b) {      
      temp = a;
      a = b;
      b = temp;
    }
    while(b != 0) {
      temp = b;
      b = a % b;
      a = temp;
    }
    return a;
  }
}

Output

Enter first number
440
Enter second number
550
GCD is 110
Enter first number
17
Enter second number
37
GCD is 1

That's all for this topic Greatest Common Divisor (GCD) of Two Numbers Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Convert int to String in Java
  2. Convert float to int in Java
  3. Arrange Non-Negative Integers to Form Largest Number - Java Program
  4. How to Convert Date to String in Java
  5. Java String Interview Questions And Answers

You may also like-

  1. Matrix Multiplication Java Program
  2. Reading Delimited File in Java Using Scanner
  3. How to Untar a File in Java
  4. static Block in Java
  5. Is String Thread Safe in Java
  6. Try-With-Resources in Java With Examples
  7. Java ThreadLocal Class With Examples
  8. AtomicLong in Java With Examples

Monday, September 1, 2025

Spring Boot Unit Test For REST API

In this article we'll see how to unit test Spring Boot REST API. As the name "unit test" itself suggests classes should be tested in isolation so in this tutorial we'll write unit tests for Controller class.

Please refer this post- Spring Boot + Data JPA + MySQL REST API CRUD Example to see the Controller class for which we are going to write unit tests.

Annotations and Classes used for writing unit tests in Spring Boot

First of all, ensure spring-boot-starter-test dependency is included. If you are using Maven then this dependency can be included in pom.xml like this.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

This starter bundles together common testing libraries like JUnit, Mockito, AssertJ, Spring Boot Test etc.

@WebMvcTest Annotation

It is a specialized annotation that can be used for a Spring MVC test that focuses only on Spring MVC components. Using this annotation disables the full auto-configuration and only enables auto-configuration that is relevant to MVC tests. Similarly, component scanning is limited to beans annotated with:

  • @Controller
  • @ControllerAdvice
  • @JsonComponent

It focuses on testing controllers and other web-related components in isolation, without loading the entire Spring application context.

MockMvc class

MockMvc provides support for testing Spring MVC applications. With MockMvc you don't require to run a web server, MockMvc simulates the full Spring MVC request handling using mock request and response objects.

@MockitoBean annotation

@MockitoBean annotation in Spring Framework is used in test classes to create a mock object. Since we are testing Controller class in isolation so any controller's dependencies on service layer, repository layer is handled using mock instances.

Note that Spring framework leverages the Mockito library to create and manage the mock objects which are used to create stub methods and verify returned values.

Note that @MockitoBean annotation was introduced in Spring Framework 6.2 it replaces @MockBean, which is now deprecated.

For example, if you want to test the UserController class then basic setup using the above mentioned annotations and classes would be as given below-

@WebMvcTest(UserController.class)
public class UserControllerTest {
	@Autowired
	private MockMvc mockmvc;
	@MockitoBean
	private UserService userService;

	@Test
	public void testAddUserReturningBadRequest() throws Exception{
		…
		…
  }
}

Writing unit tests for Spring Boot REST API

Here we want to write unit tests for UserController class which has dependency on UserService and provides methods for adding user (POST), getting all users and getting user by id (GET), updating user (PUT) and delete user by id (DELETE).

If you analyze the code for adding a new user, scenarios you can test are-

  1. If User bean fails validation; which results in MethodArgumentNotValidException being thrown.
  2. If same user is added again; which results in UserAlreadyExistsException being thrown.
  3. All values are correct and the new user is added. Response status sent is 201 (Created) and created user is also returned as response body.

Here is the method that is written in UserController annotated with @PostMapping

// Insert user record
@PostMapping
public ResponseEntity<User> addUser(@Valid @RequestBody User user) {
  User createdUser = userService.addUser(user);
  return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}

If you have to write unit tests for the above mentioned scenario 1 and 3 then that is how you can write the tests.

@WebMvcTest(UserController.class)
public class UserControllerTest {
	@Autowired
	private MockMvc mockmvc;
	@Autowired
	private ObjectMapper objectMapper;
	@MockitoBean
	private UserService userService;
	
	@Test
	public void testAddUserReturningBadRequest() throws Exception{
		User user = new User();
		user.setFirstName("");
		user.setLastName("Tiwari");
		user.setUserType("Platinum");
		user.setStartDate(LocalDate.of(2025, 8, 26));
		
		mockmvc.perform(post("/user").contentType(MediaType.APPLICATION_JSON)
				 .content(objectMapper.writeValueAsString(user)))
        		 .andExpect(status().isBadRequest())
        		 .andDo(print());
	}

	@Test
	public void testAddUserReturningCreated() throws Exception{
		User user = new User();
		user.setFirstName("Ram");
		user.setLastName("Tiwari");
		user.setUserType("Platinum");
		user.setStartDate(LocalDate.of(2025, 8, 26));
		// sending Id also
		user.setUserId(1);
		Mockito.when(userService.addUser(any(User.class))).thenReturn(user);
		mockmvc.perform(post("/user").contentType(MediaType.APPLICATION_JSON)
				 .content(objectMapper.writeValueAsString(user)))
        		 .andExpect(status().isCreated())
        		 .andExpect(jsonPath("$.firstName").value("Ram"))
        		 .andExpect(jsonPath("$.userId").value(1))
        		 .andDo(print());        		 		
	}
}

Important points to note here are-

  1. Method testAddUserReturningBadRequest() tests the scenario, if validation fails and method testAddUserReturningCreated() tests the scenario when new user is added.
  2. With Post mapping, you need to send the resource as part of request body in the form of JSON. For that ObjectMapper, provided by Jackson library, is used which converts Java object to and from JSON.
  3. perform method of MockMvc is used to perform a request that uses any Http method (in this case POST), send the type of content and the request body.
  4. You can define expectations by appending one or more andExpect(..) calls after performing a request. These andExpect() methods use MockMvcResultMatchers to assert on the HTTP status, response headers, and response body content. For example andExpect(status().isCreated()), andExpect(jsonPath("$.FIELD_NAME").value("EXPECTED_VALUE"))
  5. andDo(print()) is used to print the details of a MockHttpServletRequest and MockHttpServletResponse to the console during a test execution.
  6. In the method testAddUserReturningCreated(), Mockito.when() is used to specify the return value when the method is called on the mock object. In the above example it specifies; when userService.addUser() is called from the UserController then use the mocked userService instance and return the user object itself.
    Mockito.when(userService.addUser(any(User.class))).thenReturn(user);
    
  7. Notice the use of any() in the userService.addUser() call. It specifies that any user object will do. If you want the exact same user instance to be used then ensure that the User class implements hashCode() and equals() method to enforce object identity. Then you can use Mockito.when() as given below.
    Mockito.when(userService.addUser(user)).thenReturn(user);
    

Same way you can write unit tests for other methods in the UserController class. Here is the complete UserControllerTest class.

UserControllerTest.java

import static org.mockito.ArgumentMatchers.any;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netjstech.exception.ResourceNotFoundException;
import com.netjstech.model.User;
import com.netjstech.service.UserService;

@WebMvcTest(UserController.class)
public class UserControllerTest {
  @Autowired
  private MockMvc mockmvc;
  @Autowired
  private ObjectMapper objectMapper;
  @MockitoBean
  private UserService userService;
  
//  @Test
//  void test() {
//    fail("Not yet implemented");
//  }
  
  
  @Test
  public void testAddUserReturningBadRequest() throws Exception{
    User user = new User();
    user.setFirstName("");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    

    mockmvc.perform(post("/user").contentType(MediaType.APPLICATION_JSON)
         .content(objectMapper.writeValueAsString(user)))
             .andExpect(status().isBadRequest())
             .andDo(print());    
  }

  @Test
  public void testAddUserReturningCreated() throws Exception{
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    // sending Id also
    user.setUserId(1);
    Mockito.when(userService.addUser(any(User.class))).thenReturn(user);
    mockmvc.perform(post("/user").contentType(MediaType.APPLICATION_JSON)
         .content(objectMapper.writeValueAsString(user)))
             .andExpect(status().isCreated())
             .andExpect(jsonPath("$.firstName").value("Ram"))
             .andExpect(jsonPath("$.userId").value(1))
             .andDo(print());                 
  }
  
  @Test
  public void testGetAllUsers() throws Exception{
    List<User> userList = new ArrayList<>();
    User user1 = new User();
    user1.setUserId(1);
    user1.setFirstName("Ram");
    user1.setLastName("Tiwari");
    user1.setUserType("Platinum");
    user1.setStartDate(LocalDate.of(2025, 8, 26));
    
    User user2 = new User();
    user2.setUserId(2);
    user2.setFirstName("Shyam");
    user2.setLastName("Sharma");
    user2.setUserType("Gold");
    user2.setStartDate(LocalDate.of(2025, 7, 22));
    userList.add(user1);
    userList.add(user2);
    Mockito.when(userService.getAllUsers()).thenReturn(userList);
    
    mockmvc.perform(get("/user/allusers"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$[0].firstName").value("Ram"))
        .andExpect(jsonPath("$[1].firstName").value("Shyam"))
        .andDo(print());
  }
  
  @Test
  public void testGetUserReturningResourceNotFound() throws Exception{
    int userId = 1;
    
    Mockito.when(userService.getUserById(userId)).thenThrow(new ResourceNotFoundException("User with ID " + userId + " not found"));
    
    mockmvc.perform(get("/user/"+userId)).andExpect(status().isNotFound())
    .andExpect(content().json("{\"message\": \"Resource Not Found\"}"))
    .andExpect(jsonPath("$.exceptionMessage").value("User with ID " + userId + " not found"))
    .andDo(print());
    
  }
  
  @Test
  public void testGetUserReturningOK() throws Exception{
    int userId = 1;
    User user = new User();
    user.setUserId(1);
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    Mockito.when(userService.getUserById(userId)).thenReturn(user);
    
    mockmvc.perform(get("/user/"+userId)).andExpect(status().isOk())
    .andExpect(jsonPath("$.firstName").value("Ram"))
    .andExpect(jsonPath("$.lastName").value("Tiwari"))
    .andDo(print());
  }
  
  @Test
  public void testUpdateUserReturningResourceNotFound() throws Exception{
    User user = new User();
    user.setUserId(100);
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    
    Mockito.when(userService.updateUser(user))
          .thenThrow(new ResourceNotFoundException("User with ID " + user.getUserId() + " not found"));
    
    mockmvc.perform(put("/user").contentType(MediaType.APPLICATION_JSON)
         .content(objectMapper.writeValueAsString(user)))
         .andExpect(status().isNotFound())
         .andExpect(content().json("{\"message\": \"Resource Not Found\"}"))
         .andExpect(jsonPath("$.exceptionMessage").value("User with ID " + user.getUserId() + " not found"))
         .andDo(print());
    
  }
  
  @Test
  public void testUpdateUserReturningOK() throws Exception{
    User user = new User();
    user.setUserId(1);
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    
    User updatedUser = new User();
    updatedUser.setUserId(1);
    updatedUser.setFirstName("Ram");
    updatedUser.setLastName("Tiwari");
    updatedUser.setUserType("Gold");
    updatedUser.setStartDate(LocalDate.of(2025, 8, 26));
    
    Mockito.when(userService.updateUser(user))
          .thenReturn(updatedUser);
    
    mockmvc.perform(put("/user").contentType(MediaType.APPLICATION_JSON)
         .content(objectMapper.writeValueAsString(user)))
         .andExpect(status().isOk())
         .andExpect(jsonPath("$.userType").value("Gold"))
         .andDo(print());
    
  }
  
  @Test
  public void testDeleteUserReturningResourceNotFound() throws Exception{
    int userId = 100;
    Mockito.doThrow(new ResourceNotFoundException("User with ID " + userId + " not found"))
    .when(userService).deleteUserById(userId);
    
    mockmvc.perform(delete("/user/"+userId))
         .andExpect(status().isNotFound())
         .andExpect(content().json("{\"message\": \"Resource Not Found\"}"))
         .andExpect(jsonPath("$.exceptionMessage").value("User with ID " + userId + " not found"))
         .andDo(print());
    
  }
  
  @Test
  public void testDeleteUserReturningOK() throws Exception{
    int userId = 1;

        Mockito.doNothing().when(userService).deleteUserById(userId);
        //Mockito.verify(userService, Mockito.times(1)).deleteUserById(userId);
        mockmvc.perform(delete("/user/"+userId))
         .andExpect(status().isNoContent())
         .andDo(print());
    
  }

}

Some of the points to note here are-

  1. In the method testGetUserReturningResourceNotFound(), Mockito.when().thenThrow() is used to specify the exception that has to be thrown by the mock object to test user id not found scenario.
  2. Method testGetUserReturningResourceNotFound() shows another way to extract properties from JSON other than using jsonPath.
    andExpect(content().json("{\"message\": \"Resource Not Found\"}"))
    
  3. Method deleteUserById() in the actual UserServiceImpl class doesn't return any value so unit test for that also needs to mock userservice call with that expectation.
    Mockito.doNothing().when(userService).deleteUserById(userId);
    

That's all for this topic Spring Boot Unit Test For REST API. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring Boot Data JPA Repository Unit Test
  2. Spring Boot + Spring Security JWT Authentication Example
  3. Spring Data JPA - Spring Data Tutorial
  4. Spring Boot Observability - Distributed Tracing, Metrics
  5. Spring Bean Life Cycle

You may also like-

  1. BeanPostProcessor in Spring Framework
  2. Transaction Management in Spring
  3. Spring Web Reactive Framework - Spring WebFlux Tutorial
  4. Spring JdbcTemplate Insert, Update And Delete Example
  5. JVM Run-Time Data Areas - Java Memory Allocation
  6. Comparing Enum to String in Java
  7. Python Lambda Functions With Examples
  8. Angular ngClass Directive With Examples

Tuesday, August 26, 2025

Spring Boot + Data JPA + MySQL REST API CRUD Example

In this post Spring Data tutorial we got to know about Spring Data and how to use it. In this tutorial we'll create a Spring Boot REST API CRUD application using Spring Data JPA and MySQL database. We'll also see how to do exception handling with Spring Boot REST API.


Wednesday, July 30, 2025

Python Lambda Functions With Examples

Python lambda function is a function without any name (an anonymous function) which is created using lambda keyword. Syntax of lambda function in Python is as given below.

lambda argument(s):expression

Any lambda function starts with the keyword lambda.

  • argument(s)- Parameters passed to the lambda function. Number of parameters can be 0…n.
  • expression- Logic of the lambda function.

Lambda function examples

Here is a simple example of lambda function that squares the passed number.

lambda num : num**2

Here num is the argument which is on the left side of the colon (:) and right side of it is the logic that will be executed when this lambda function is called.

The above lambda function is equivalent to the following regular function.

def square(num):
    return num ** 2

In order to execute this lambda function you can assign it to a variable. That variable essentially holds the lambda function so it can be called like a regular function using this variable.

square = lambda num : num**2
print(square(9)) #81

Another way is to immediately invoke it-

(lambda num : num**2)(9)

Some other examples of lambda functions.

1. With out any argument

msg = lambda :print("Hello")

msg() # Hello

2. Lambda function with one argument.

msg = lambda m : print(m)

msg("Hello there") # Hello there

3. Lambda function with two arguments. Gets the max of two numbers.

max = lambda x, y : x if x > y else y

print(max(17, 14)) #17

When to use lambda functions

  1. For simple operations- When logic is simple enough to be expressed in a single line and a function is needed for one time use, lambda function is a more concise and readable alternative to regular function.
  2. Used as argument for higher order functions- Higher order functions like map, filter, sorted which need another function as argument can use lambda function as that argument. That allows for the inline implementation of the function logic needed as argument in these higher order functions.

That's all for this topic Python Lambda Functions With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Variable Length Arguments (*args), Keyword Varargs (**kwargs) in Python
  2. Python Generator, Generator Expression, Yield Statement
  3. Python Functions: Returning Multiple Values
  4. Global Keyword in Python With Examples
  5. Namespace And Variable Scope in Python

You may also like-

  1. Python String split() Method
  2. Convert String to int in Python
  3. Magic Methods in Python With Examples
  4. List Comprehension in Python With Examples
  5. Lambda Expressions in Java 8
  6. Java Map putIfAbsent() With Examples
  7. Spring Setter Based Dependency Injection
  8. Data Loader in React Router

Thursday, June 26, 2025

Virtual Threads in Java

In this tutorial we'll see what are virtual threads in Java which are added in Java 21.

Platform threads

Traditional threads which we created till now by implementing Runnable, extending Thread class or by using Executor Service to create thread pools are now known as Platform threads. So, you can say now we have two types of threads which you can create.

  1. Platform Thread
  2. Virtual Thread

When a thread is started, it is scheduled by JVM to run (Thread goes to runnable state) but actual execution of the thread is done by the underlying OS by mapping the platform thread to OS thread. A platform thread is implemented as a thin wrapper around an operating system (OS) thread which means number of available platform threads is limited to the number of OS threads. In other words, you can say scalability of platform threads is limited by the number of available OS threads.

Virtual threads in Java

Virtual threads are also an instance of java.lang.Thread so that way these threads are similar to platform threads. How they differ from platform thread is that virtual threads are implemented by the Java runtime rather than the OS.

Unlike platform thread a virtual thread isn't tied to a specific OS thread which means number of virtual threads is not limited by OS threads. You can have a lot of active virtual threads, even millions, running in the same Java process.

That is the advantage of virtual threads, they provide scale (higher throughput).

How does Virtual thread execute

A virtual thread still runs code on an OS thread, whole process goes as explained below-

  1. The Java runtime schedules a virtual thread
  2. Java runtime assigns or mounts the virtual thread on a platform thread. This platform thread is called a carrier
  3. The underlying OS schedules that platform thread by mapping it to OS thread.
  4. Virtual thread starts its execution. If the mounted virtual thread is performing a blocking I/O operation it can unmount from its carrier.
  5. Now the carrier is free and Java runtime scheduler can mount a different virtual thread on it.

When to use Virtual threads

Platform threads generally have a large thread stack and other resources that are maintained by the OS whereas virtual threads typically have a shallow call stack which means virtual threads are light weight but that doesn't mean they are any faster than platform threads.

What virtual threads provide is scale not speed. Virtual threads are suitable for running tasks that spend most of the time blocked, often waiting for I/O operations to complete. However, they aren't intended for long-running CPU-intensive operations.

How to create Virtual threads in Java

1. Using startVirtualThread(Runnable task) method

In Thread class there is a static method startVirtualThread(Runnable task) which creates a virtual thread to execute a task and schedules it to execute.

public class VTDemo {
  public static void main(String[] args) {
    Runnable r = () -> System.out.println("Running a task"); 

    Thread virtualThread = Thread.startVirtualThread(r);
    
    try {
      virtualThread.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

2. Using ofVirtual() method of Thread class

This method returns a builder for creating a virtual Thread or ThreadFactory that creates virtual threads.

public class VTDemo {
  public static void main(String[] args) {
    Runnable r = () -> System.out.println("Running a task"); 
    Thread virtualThread = Thread.ofVirtual().start(r);
    try {
      virtualThread.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

Thread.Builder interface has two subinterfaces

  1. Thread.Builder.OfPlatform- Builder of platform threads.
  2. Thread.Builder.OfVirtual- Builder of virtual threads.

Thread.Builder example

public class VTDemo {
  public static void main(String[] args) {
    Runnable r = () -> System.out.println("Running a task"); 
    Thread.Builder builder = Thread.ofVirtual();
    // set the name for threads
    builder.name("worker-", 0);
    Thread t1 = builder.start(r);   
    Thread t2 = builder.start(r);   
    try {
      t1.join();
      t2.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    
    System.out.println(t1.getName() + " terminated");
    System.out.println(t2.getName() + " terminated");
  }
}

ThreadFactory of virtual thread example

Thread.Builder has a factory() method that returns a ThreadFactory to create threads from the current state of the builder.

Executors class has methods like newFixedThreadPool(), newCachedThreadPool() which take ThreadFactory as parameter.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;

public class VTFactoryDemo {
  public static void main(String[] args) {
    ThreadFactory virtualThreadFactory = Thread.ofVirtual().factory();
    ExecutorService es = Executors.newFixedThreadPool(5, virtualThreadFactory);
    Callable<String> c = () -> "Call from thread";
    Future<String> f =  es.submit(c);
    try {
      System.out.println(f.get());
    } catch (InterruptedException | ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    es.shutdown();
  }
}

3. Executors.newVirtualThreadPerTaskExecutor() Method

This method creates an Executor that starts a new virtual Thread for each task. The number of threads created by the Executor is unbounded.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class VTFactoryDemo {
  public static void main(String[] args) throws InterruptedException, ExecutionException {
    try (ExecutorService es = Executors.newVirtualThreadPerTaskExecutor()) {
      Callable<String> c = () -> "Call from thread";
      Future<String> f =  es.submit(c);
      System.out.println(f.get());  
    }
  }
}

Source: https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html

That's all for this topic Virtual Threads in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java ThreadLocal Class With Examples
  2. Volatile Keyword in Java With Examples
  3. Lock Striping in Java Concurrency
  4. CompletableFuture in Java With Examples
  5. Java ArrayBlockingQueue With Examples

You may also like-

  1. Java Nested Class And Inner Class
  2. CopyOnWriteArrayList in Java With Examples
  3. Java Sealed Classes and Interfaces
  4. Why no Multiple Inheritance in Java
  5. Nested Route in React Router With Example
  6. String Slicing in Python
  7. ServiceLocatorFactoryBean in Spring
  8. Angular Event Binding With Examples

Monday, June 23, 2025

Spring Boot + Spring Security JWT Authentication Example

In this tutorial we’ll see how to create a Spring Boot application that uses Spring Security and JWT token based authentication to bring authentication and authorization to the exposed REST APIs. DB used is MySQL.

What does JWT do

JWT (JSON Web Token) is used for securing REST APIs.

In the JWT authentication process a client application first need to authenticate using credentials. The server side verifies the sent credentials, if valid then it generates and returns a JWT.

Once the client has been authenticated it has to sent the token in the request’s Authorization header in the Bearer Token form with each request. The server will check the validity of the token to verify the validity of the client and authorize or reject requests. You can also store roles and method usage will be authorized based on the role.

You can also configure the URLs that should be authenticated and those that will be permitted without authentication.

Spring Boot + Spring Security with JWT authentication example

In the application we’ll have the user signup and user login logic. Once the signup is done user should be authenticated when logging in, that configuration would be done using Spring security and JWT.