【问题标题】:Unit test for Save method of JPA Repository in Spring BootSpring Boot中JPA Repository的Save方法的单元测试
【发布时间】:2020-12-11 01:06:48
【问题描述】:

您能告诉我应该如何使用 Mockito 和 JUnit 为这段代码编写单元测试吗? StudentRepository 是一个扩展 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);
    }
}

【问题讨论】:

    标签: spring-boot junit mockito junit4


    【解决方案1】:

    首先,您希望构造函数注入优于字段注入。如果没有 studentRepository 的依赖,studentService 将无法工作。更改后,您可以使用 Mockito 进行单元测试。采取的步骤:

    1. 在 junit 5 的情况下使用 ExtendsWith(MockitoExtension.class) 或在 JUnit 4 的情况下使用 @RunWith(MockitoJunit4ClassRunner.class) 注释类。
    2. 通过使用@Mock 注释该类型的变量来创建StudentRepository Mock
    3. 通过使用@InjectMocks 注释服务的变量将模拟注入服务
    4. 那么您想定义模拟行为。您可以在构造时使用模拟来执行此操作。类似于when(studentRepository.myMethod()).thenReturn(MyCustomObject())
    5. 调用服务方法
    6. 断言有关您的服务的某些行为。例如,您可以使用 mockito 的 verify 构造来测试 studentRepository.save() 是否被调用一次。附带说明一下,保存不应返回 void,而应实际返回实体本身。

    【讨论】:

      【解决方案2】:

      几天前我也遇到过同样的情况,我想到了这样的事情。

      @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());
      }
      

      您也可以使用 ArgumentCaptor 并检查您传递来保存的对象是否是您想要的,它可能看起来像这样

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

      【讨论】:

        【解决方案3】:

        你的方法做了两件事,很难测试。

        该方法首先从 StudentModel 创建一个 Student 对象,然后保存 Student 对象。

        您可以将两者分开,将 Student 创建提取到单独的方法中(可以在您的服务中,但也可以在 Student 或 StudentModel 类中)。如果您愿意,您可以单独对该方法进行单元测试。这避免了通过 ArgumentCaptor 进行测试的需要。

        有了这个,您可以按照Daniel’sBorsuk’s 的回答来验证您的服务是否确实调用了存储库的保存方法。

        【讨论】:

          猜你喜欢
          • 2021-06-19
          • 2022-11-11
          • 1970-01-01
          • 2019-01-23
          • 2015-07-09
          • 1970-01-01
          • 2017-02-08
          • 2018-03-01
          • 2016-05-28
          相关资源
          最近更新 更多