如何单元测试ResultSetExtractor?

时间:2018-03-31 23:41:22

标签: java unit-testing junit mockito

在使用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);
  }

使用匿名类的上述方法,我将不得不使用argumentCaptor来获取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;
    }
  }

下面的测试将通过任一实现,但我想避免使用任何(ResultSetExtractor.class)。我想要的是尽可能测试extractData(最终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));
  }

1 个答案:

答案 0 :(得分:3)

您可以执行以下操作

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