Spring Boot EasyMock Tutorial

Introduction

EasyMock is a testing framework for Java that allows you to create mock objects for interfaces and classes. It simplifies the creation of test doubles for unit testing. In this tutorial, we will cover how to use EasyMock in a Spring Boot application to test CRUD (Create, Read, Update, Delete) operations.

To learn more about EasyMock, check out this guide: EasyMock.

Prerequisites

  1. Java Development Kit (JDK) 17 or later
  2. Apache Maven installed
  3. An IDE like IntelliJ IDEA or Eclipse

Step 1: Create a Spring Boot Project

You can create a Spring Boot project using Spring Initializr or your IDE.

Using Spring Initializr

  1. Go to Spring Initializr.
  2. Select the following options:
    • Project: Maven Project
    • Language: Java
    • Spring Boot: 3.0.0 or later
    • Group: com.example
    • Artifact: easymock-demo
    • Name: easymock-demo
    • Package name: com.example.easymockdemo
    • Packaging: Jar
    • Java: 17 or later
  3. Add the following dependencies:
    • Spring Web
    • Spring Data JPA
    • H2 Database
    • Spring Boot Starter Test
  4. Click "Generate" to download the project zip file.
  5. Extract the zip file and open the project in your IDE.

Step 2: Add EasyMock Dependencies

Add the following dependencies to your pom.xml file:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

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

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- EasyMock -->
    <dependency>
        <groupId>org.easymock</groupId>
        <artifactId>easymock</artifactId>
        <version>5.0.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Step 3: Configure Application Properties

Add the following properties to src/main/resources/application.properties:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

Step 4: Create the Entity Class

Create a new Java class named User in the com.example.easymockdemo package:

package com.example.easymockdemo;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

Explanation: The User class is a JPA entity that represents a user in our system. It has an id, name, and email field. The @Entity annotation specifies that this class is an entity and is mapped to a database table.

Step 5: Create the Repository Interface

Create a new Java interface named UserRepository in the com.example.easymockdemo package:

package com.example.easymockdemo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

Explanation: The UserRepository interface extends JpaRepository, which provides JPA related methods for standard data access operations. This interface will be used to interact with the database.

Step 6: Create the Service Class

Create a new Java class named UserService in the com.example.easymockdemo package:

package com.example.easymockdemo;

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

import java.util.List;
import java.util.Optional;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List<User> findAll() {
        return userRepository.findAll();
    }

    public Optional<User> findById(Long id) {
        return userRepository.findById(id);
    }

    public User save(User user) {
        return userRepository.save(user);
    }

    public void deleteById(Long id) {
        userRepository.deleteById(id);
    }
}

Explanation: The UserService class contains methods for CRUD operations. It uses UserRepository to interact with the database. The @Service annotation indicates that this class is a service component in the Spring context.

Step 7: Create the Controller Class

Create a new Java class named UserController in the com.example.easymockdemo package:

package com.example.easymockdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAll();
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        return userService.findById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }

    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        return userService.findById(id)
                .map(existingUser -> {
                    user.setId(existingUser.getId());
                    return ResponseEntity.ok(userService.save(user));
                })
                .orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        return userService.findById(id)
                .map(user -> {
                    userService.deleteById(id);
                    return ResponseEntity.noContent().build();
                })
                .orElse(ResponseEntity.notFound().build());
    }
}

Explanation: The UserController class handles HTTP requests and responses. It uses UserService to perform CRUD operations. The @RestController annotation indicates that this class is a RESTful controller. The @RequestMapping("/users") annotation maps HTTP requests to /users to the methods in this controller.

Step 8: Create the Main Application Class

Create a main application class named EasyMockDemoApplication in the com.example.easymockdemo package:

package com.example.easymockdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class EasyMockDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(EasyMockDemoApplication.class, args);
    }
}

Explanation: The EasyMockDemoApplication class contains the main method, which is the entry point of the Spring Boot application. The @SpringBootApplication annotation is a convenience annotation that adds all the following:

  • @Configuration: Tags the class as a source of bean definitions for the application context.
  • @EnableAutoConfiguration: Tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
  • @ComponentScan: Tells Spring to look for other components, configurations, and services in the specified package.

Step 9: Create EasyMock Test Class

Create a new test class named UserServiceTest in the src/test/java/com/example/easymockdemo package:

package com.example.easymockdemo;

import org.easymock.EasyMock;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

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

import static org.junit.jupiter.api.Assertions.assertEquals;


import static org.junit.jupiter.api.Assertions.assertTrue;

@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @MockBean
    private UserRepository userRepository;

    @BeforeEach
    public void setUp() {
        User user1 = new User();
        user1.setId(1L);
        user1.setName("Rajesh");
        user1.setEmail("rajesh@example.com");

        User user2 = new User();
        user2.setId(2L);
        user2.setName("Suresh");
        user2.setEmail("suresh@example.com");

        List<User> users = Arrays.asList(user1, user2);

        EasyMock.expect(userRepository.findAll()).andReturn(users);
        EasyMock.expect(userRepository.findById(1L)).andReturn(Optional.of(user1));
        EasyMock.expect(userRepository.save(user1)).andReturn(user1);
        userRepository.deleteById(1L);
        EasyMock.expectLastCall();

        EasyMock.replay(userRepository);
    }

    @Test
    public void testFindAll() {
        List<User> users = userService.findAll();
        assertEquals(2, users.size());
    }

    @Test
    public void testFindById() {
        Optional<User> user = userService.findById(1L);
        assertTrue(user.isPresent());
        assertEquals("Rajesh", user.get().getName());
    }

    @Test
    public void testSave() {
        User user = new User();
        user.setId(1L);
        user.setName("Rajesh");
        user.setEmail("rajesh@example.com");

        User savedUser = userService.save(user);
        assertEquals("Rajesh", savedUser.getName());
    }

    @Test
    public void testDeleteById() {
        userService.deleteById(1L);
        EasyMock.verify(userRepository);
    }
}

Explanation: This test class uses EasyMock to mock the UserRepository and test the UserService

The @SpringBootTest annotation tells Spring Boot to look for a main configuration class and use that to start a Spring application context. 

The @MockBean annotation tells Spring Boot to create a mock instance of UserRepository and inject it into the UserService.

Step 10: Run the Tests

Run the tests using your IDE or by executing the following command in the terminal:

mvn test

You should see output indicating that all tests have passed successfully.

Conclusion

In this tutorial, we demonstrated how to use EasyMock to test CRUD operations in a Spring Boot application. We created a simple Spring Boot application, added EasyMock dependencies, and wrote tests to mock the UserRepository and test the UserService

By following these steps, you can efficiently test your Spring Boot applications and ensure that your CRUD operations work as expected. This approach allows you to create mock objects and verify their interactions, making your tests more robust and reliable.

To learn more about EasyMock, check out this guide: EasyMock.

Comments