简体   繁体   中英

How to unit test ResultSetExtractor?

I need advice on how to unit test a ResultSetExtractor when using jdbc.

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

With the above approach of using an anonymous class, I would have to use argumentCaptor to get the ResultSetExtractor. The test I have so far is below. I don't know how what to do next in terms of the 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);
  }

I dont know if using an anonymous class would make it harder to unit test. I could always pull the anonymous class out of the jdbc call and make a class like below, but I dont know where to start testing this class.

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

The test below would pass with either implementations but I want to avoid using any(ResultSetExtractor.class). What I want is to test the actual implementation of extractData(final ResultSet rs) if possible.

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

You could do the following

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM