用于 RowMapper 的 Spring jdbc 模板的单元测试用例

Posted

技术标签:

【中文标题】用于 RowMapper 的 Spring jdbc 模板的单元测试用例【英文标题】:Unit Test Case For Spring jdbc template for RowMapper 【发布时间】:2020-07-22 13:18:12 【问题描述】:

我知道为 mapper 编写单元测试或设置不是一件好事,但它就是这样,所以我被困在如何为 mapper 进行单元测试;

学生组列表如下;

@Getter
@Setter
public class StudentGroupList 

 private String studentId;

StudentGroupListRowMapper 下面;

public class StudentGroupListRowMapper implements RowMapper<StudentGroupList> 

  @Override
  public StudentGroupList mapRow(Resultset rs, int rowNum) throws SQLException 

  StudentGroupList studentGroupList = new StudentGroupList();
 
  studentGroupList.setStudentId(rs.getString("student_id"));

  return studentGroupList;
 

我在下面尝试过,但是 jococo 覆盖率测试没有覆盖任何东西

   public class TaskGroupListRowMapperTest 

     private ResultSet resultSet;
     private StudentGroupList studentGroupList;

     @Before
     public void setUp() 
     resultSet = mock(ResultSet.class);
     studentGroupList = mock(StudentGroupList.class);
    

    @Test
    public void testStudentGroupListMapper() throws SQLException 
     when(resultSet.getString("student_id"))
    .thenReturn(studentGroupList.getStudentID());
     
    assertTrue(studentGroupList.getStudentId(), true);
    
 

它说异常; thenReturn() 可能会丢失。

【问题讨论】:

我的意思是 DAO 层通常没有经过测试,但它比上次 (***.com/questions/63001810/…) 当你想测试构造函数时有了很大的改进,所以还不错:) 你仍然会得到减号投票(不是来自我,但仍然是),因为您不是针对特定问题寻求帮助,您只是希望我们为您编写测试 感谢您的回答,但下次我可以自己编写测试,因为我从未为 mapper 编写过单元测试 @JAsgarow 请查看我的更新答案 那个测试类完全没有任何意义。为什么它实现RowMapper?你想测试StudentGroupListRowMapper 然后测试它。目前你什么都没有测试(这也是 Jacoco 告诉你的!)。为ResultSet 创建一个模拟(使用类似 Mockito 的东西)。调用 rowmapper 上的方法并断言结果是正确的。 【参考方案1】:

放轻松,我们过去都在那里,试图了解单元测试应该做什么。

您不会为了单元测试覆盖率而对所有内容进行单元测试。当您有像 RowMapper 这样的框架回调时,就是其中一种情况。您的StudentGroupListRowMapper 非常简单,因此您的 Dao 的集成测试将涵盖它。无论如何,您想进行单元测试,所以只需将其视为一个简单的类,让我们逐步完成。

您想要创建要测试的类的实例,并为它调用的任何服务提供模拟依赖项。幸运的是,您的 StudentGroupListRowMapper 没有打电话。 由于您要测试的方法是StudentGroupList mapRow(Resultset rs, int rowNum),因此您必须决定是否可以提供ResultsetrowNum。由于Resultset 不是您创建的,因此您为此提供了一个模拟

    Resultset inputRs = mock(Resultset.class);
    int rowNum = 1;
   
现在,当你的方法执行时,它会调用inputRs.getString("student_id") 来获取学生ID,但它是模拟的,它不知道返回什么,所以你必须告诉你的模拟在调用inputRs.getString("student_id") 时要做什么
   when(inputRs.getString("student_id")).thenReturn("sutdent-id-1");
现在您知道应该使用 "sutdent-id-1" 创建预期的 StudentGroupList,并且应该从该方法返回。

assertEquals(resultedStudentGroupList.getStudentId(),"sutdent-id-1");

让我们将所有这些组合在一起。
   public class StudentGroupListRowMapperTest 

    StudentGroupListRowMapper mapper = new StudentGroupListRowMapper();
 
    @Test
    public void testMapRow() 
      Resultset inputRs = mock(Resultset.class);
      int rowNum = 1;
      when(inputRs.getString("student_id")).thenReturn("sutdent-id-1");

      StudentGroupList result = mapper.mapRow(inputRs, rowNum);

      assertEquals(result.getStudentId(), "sutdent-id-1");
    
  

【讨论】:

非常感谢您的晚餐解释。可以说我有 8 或 9 行让我们说;我有学生姓名,姓氏等。我必须输入 int rowNum 8 sth 那是集成测试。您正在测试的方法mapRow 只关心如何映射单行。它不关心重新调整了多少行或 dao 的总结果是什么。当你进行单元测试时,忘记一切,只考虑输入是什么,什么是东西,它在那个方法里面做 时间戳呢?我的意思是我已经尝试过 when(inputRs.getTimeStamp("student_date").toLocalDateTime()).thenReturn(LocalDateTime.of(2019,2,14,6,11))); assertEquals(result.getStudentDate, LocalDateTime.of(2019,2,14,6,11));我得到空指针异常

以上是关于用于 RowMapper 的 Spring jdbc 模板的单元测试用例的主要内容,如果未能解决你的问题,请参考以下文章

一个加速产生 Spring JDBC RowMapper 的工具类

Spring中JdbcTemplate中使用RowMapper

spring 中的 RowMapper

Spring Framework应用中JDBC使用RowMapper的一些疑惑

Spring RowMapper 接口究竟是如何工作的?

RowMapper问题