Unit test for Save method of JPA Repository in Spring Boot

Viewed 7926

Can you please tell me how I should write unit tests for this code using Mockito & JUnit? StudentRepository is an interface which extends JPA Repository.

public class StudentService {
    @Autowired
    StudentRepository studentRepository;
    
    public void saveStudentDetails(StudentModel student) {
        Student stud = new Student();
        stud.setStudentId(student.getStudentId());
        stud.setStudentName(student.getStudentName());
        studentRepository.save(stud);
    }
}
3 Answers

I've been in this same situation couple days ago, and i figured something like this.

@InjectMocks
StudentService studentService;
@Mock
StudentRepository studentRepository;

public void saveStudentDetailsTest(){
    //given
    StudentModel student = new StudentModel(Your parameters);
    //when
    studentService.saveStudentDetails(student);
    //then
    verify(studentRepository, times(1)).save(any());
}

Also you can use ArgumentCaptor and check if the object you are passing to save is what you want, and it can looks like this

ArgumentCaptor<Student> captor = ArgumentCaptor.forClass(Student.class);
verify(studentRepository).save(captor.capture());
assertTrue(captor.getValue().getStudentName().equals(student.getStudentName()));

First of all you want to favor constructor injection over field injection. The studentService should not work without its dependency of studentRepository. After you have changed that you can make a unit test by using Mockito for example. Steps to take:

  1. Annotate the class with either ExtendsWith(MockitoExtension.class) in case of junit 5 or @RunWith(MockitoJunit4ClassRunner.class) in case of JUnit 4.
  2. create a StudentRepository Mock by annotating a variable of that type with @Mock
  3. inject the mock into the service by annotating a variable of the service with @InjectMocks
  4. then you want to define the mocking behavior. You can do this with mockitos when construct. It will be something like when(studentRepository.myMethod()).thenReturn(MyCustomObject())
  5. call the service method
  6. assert certain behavior about your service. For example you can use mockito's verify construct to test that studentRepository.save() is called once. As a side note a save should not return void but actually return the entity itself.

Your method does two things, making it hard to test.

The method first creates a Student object from a StudentModel, and then saves the Student object.

You can separate the two, extracting the Student creation into a separate method (could be in your service, but it could also be in the Student or StudentModel classes). The you can unit test that method separately if you wish. This avoids the need to test this via an ArgumentCaptor.

With that in place you can follow Daniel’s or Borsuk’s answer to verify that your service actually invokes the save method of the repository.

Related