我需要使用jdbc时如何对ResultSetExtractor进行单元测试的建议。

String sql = "SELECT * FROM item where item_id = ?";
    return (Item) jdbcTemplate.query(sql, new ResultSetExtractor<Item>() {
      @Override
      public Item extractData(final ResultSet rs) throws ... {
        if (rs.next()) {
          Item item = new Item (rs.getString(1), rs.getString(2));
          return item ;
        } else
          return null;
      }
    }, itemId);
  }


通过上面使用匿名类的方法,我将不得不使用argumentsCaptor来获取ResultSetExtractor。我到目前为止的测试如下。我不知道下一步该如何操作ResultSetExtractor。

 @Test
  public void testGetItemByID() {
    ArgumentCaptor<ResultSetExtractor> rseCaptor = ArgumentCaptor.forClass(ResultSetExtractor.class);
    ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
    String sql = "SELECT * FROM item where item_id = ?";
    itemDAOImpl.getItemByID(testId);
    verify(mockJdbcTemplate, times(1)).query(stringCaptor.capture(), rseCaptor.capture(), stringCaptor.capture());
    assertEquals(stringCaptor.getAllValues().get(0),sql);
    assertEquals(stringCaptor.getAllValues().get(1),testId);
  }


我不知道使用匿名类是否会使单元测试更加困难。我总是可以将匿名类从jdbc调用中拉出,并像下面这样创建一个类,但是我不知道从哪里开始测试该类。

public class ItemResultSet implements ResultSetExtractor<Item> {
    @Override
    public Item extractData(ResultSet rs) throws ...{
      if (rs.next()) {
        Item item = new Item (rs.getString(1), rs.getString(2));
        return item ;
      } else
        return null;
    }
  }


下面的测试将通过任一实现,但是我想避免使用any(ResultSetExtractor.class)。我想要的是,如果可能的话,测试extractData(final ResultSet rs)的实际实现。

@Test
  public void testGetItemByID() {
    String sql = "SELECT * FROM item where item_id = ?";
    when(mockJdbcTemplate.query(anyString(), any(ResultSetExtractor.class), anyString()))
        .thenReturn(testItem);
    assertEquals(testItem, itemDAOImpl.getItemByID(testId));
  }

最佳答案

您可以执行以下操作

private ResultSet getMockResultSet() throws Exception {
    ResultSet rs = Mockito.mock(ResultSet.class);
    Mockito.when(rs.next()).thenReturn(true).thenReturn(false);
    Mockito.when(rs.getString(1)).thenReturn("Value 1");
    Mockito.when(rs.getString(2)).thenReturn("Value 2");
    return rs;
}

private ResultSet getEmptyMockResultSet() throws Exception {
    ResultSet rs = Mockito.mock(ResultSet.class);
    Mockito.when(rs.next()).thenReturn(false);
    return rs;
}

@Test
public void testDataExists() {
    Item item = new ResultSetExtractor<Item>() {
        @Override
        public Item extractData(final ResultSet rs) throws ... {
            if (rs.next()) {
                Item item = new Item (rs.getString(1), rs.getString(2));
                return item ;
            } else
                return null;
        }
    }.extractDatae(getMockResultSet());
    assertEquals(item.getFirst(), "Value 1");
    assertEquals(item.getSecond(), "Value 2");
}


@Test
public void testNoDataExists() {
    Item item = new ResultSetExtractor<Item>() {
        @Override
        public Item extractData(final ResultSet rs) throws ... {
            if (rs.next()) {
                Item item = new Item (rs.getString(1), rs.getString(2));
                return item ;
            } else
                return null;
        }
    }.extractData(getEmptyMockResultSet());
    assertNull(item);
}

10-01 19:11
查看更多