In this article, we are going to explain in detail how to mock a repository in Spring Boot.

First, we will build a basic Spring Boot application. Then, we will illustrate how to use Mockito to unit test the service layer.

Generate Spring Boot Project

Before diving deep into the details, let’s create a simple Spring Boot application.

To do so, we will use Spring initializr to bootstrap the project quickly.

Bootstrap Spring Boot Application

Our application will be organized around 3 main layers:

  • Domain Student.java

  • Repository StudentRepository.java

  • Service StudentService.java

Create Domain Model

First, we are going to create the domain model. For instance, let’s consider the Student.java:

    
        @Entity
        public class Student {
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            private int id;
            private String firstName;
            private String lastName;
            private int age;
            private String gender;

            public int getId() {
                return id;
            }
            public void setId(int id) {
                this.id = id;
            }
            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 int getAge() {
                return age;
            }
            public void setAge(int age) {
                this.age = age;
            }
            public String getGender() {
                return gender;
            }
            public void setGender(String gender) {
                this.gender = gender;
            }
        }
    

Create JPA Repository

Secondarily, let’s create a Spring Data JPA repository for our domain Student:

    
        @Repository
        public interface StudentRepository extends JpaRepository<Student, Integer> {
        }
    

In short, StudentRepository exposes basic CRUD operations for the Student class.

Create a Business Service

Lastly, we will create a simple interface to encapsulate the business logic:

    
        public interface StudentService {
            List<Student> findAll();
            Optional<Student> findById(int id);
            Student save(Student student);
            void deleteById(int id);
        }
    

Now, let’s create a concrete implementation for our interface:

    
        @Service
        public class StudentServiceImpl implements StudentService {
            private final StudentRepository studentRepository;

            public StudentServiceImpl(StudentRepository studentRepository) {
                this.studentRepository = studentRepository;
            }
            @Override
            public List<Student> findAll() {
                return studentRepository.findAll();
            }
            @Override
            public Optional<Student> findById(int id) {
                return studentRepository.findById(id);
            }
            @Override
            public Student save(Student student) {
                return studentRepository.save(student);
            }
            @Override
            public void deleteById(int id) {
                studentRepository.deleteById(id);
            }
        }
    

As we can see, StudentServiceImpl relies on StudentRepository to perform data access logic. This is why we injected it as a dependency.

Unit Testing Service Layer

Now that we put all the pieces together, let’s see how to implement unit testing for StudentServiceImpl.

As shown above, StudentRepository is injected implicitly using the parametrized constructor.

So, in order to test the service, we need first to mock the repository. This is where Mockito comes to the rescue.

Please refer to our article on how to unit test a Spring Boot API for more detailed informations.

Mock Repository using Mockito

Mockito comes with a host of ready-to-use methods and annotations to do all the heavy lifting of mocking objects.

In short, Mockito offers two ways to create a mock for a repository:

  • @Mock annotation

  • Static method mock()

So, let’s take a close look at each option.

Using @Mock

Now, let’s move on to the unit test. First, we will be using the @Mock annotation to mock StudentRepository.

    
        @ExtendWith(MockitoExtension.class)
        class StudentServiceUnitTest {
            @Mock
            private StudentRepository studentRepository;
            @InjectMocks
            private StudentServiceImpl studentService;
        }
    
  • @ExtendWith(MockitoExtension.class) enables Mockito support

  • @InjectMocks allows to create studentService and inject the mocked studentRepository into it

For instance, let’s add a test case to test the findAll() method:

    
        @Test
        void findAll_should_return_student_list() {
            // Given
            Student student = new Student();
            student.setId(1);
            student.setFirstName("Abderrahim");
            student.setLastName("Azhrioun");
            student.setAge(20);
            student.setGender("Male");

            // When calling the mocked repository method
            when(studentRepository.findAll()).thenReturn(List.of(student));
            List students = this.studentService.findAll();

            // Then
            assertEquals(List.of(student), students);
            verify(this.studentRepository).findAll();
        }
    

test findAll Method

Another solution would be using MockitoAnnotations.initMocks(this) to initialize the annotated mocked objects. However, this method is marked as deprecated.

Using Mockito.mock()

Now let’s go ahead and see how we can use the Mockito.mock() method to achieve the same objective:

    
        class StudentServiceUnitTestV2 {
            private StudentRepository studentRepository;
            private StudentServiceImpl studentService;

            @BeforeEach
            void setup() {
                studentRepository = Mockito.mock(StudentRepository.class);
                studentService = new StudentServiceImpl(studentRepository);
            }
        }
    

The method takes the class of the object to mock as a parameter. This is why we passed StudentRepository.class.

Mocking Repository that Returns Optional

Typically, findById() returns an Optional object unlike findAll() which return a simple list.

So, how we can tell the mocked repository to return an Optional when invoking findById()?

To answer this question, we are going to create a test case:

    
        @Test
        void findById_should_return_single_student() {
            // Given
            Student student = new Student();
            student.setId(2);
            student.setFirstName("Emma");
            student.setGender("Female");

            // When calling findById returns Optional
            when(studentRepository.findById(anyInt())).thenReturn(Optional.of(student));
            Optional<Student> returnedStudent = this.studentService.findById(2);

            // Then
            assertTrue(returnedStudent.isPresent());
            verify(this.studentRepository).findById(2);
        }
    

Please notice that we used Optional.of(student) to tell thenReturn() to return an Optional when findById() is called.

testing findById Method

Conclusion

In this tutorial, we explored different ways to mock a repository in Spring Boot using Mockito.

First, we created a simple service that uses a JPA repository. Then, we explained how to mock the injected repository using practical examples.