This post shows how you can mock a java.sql.ResultSet using Mockito. It can be used to help unit test code which performs operations on ResultSets (such as a ResultSetExtractor) without relying on an external datasource.
You can create a MockResultSet by providing a list of column names and a 2D array of data. For example:
var rs = MockResultSet.create(
new String[] { "name", "age" }, //columns
new Object[][] { // data
{ "Alice", 20 },
{ "Bob", 35 },
{ "Charles", 50 }
});
The code for MockResultSet is shown below (also available in my GitHub Repository). Note that I have only mocked a few methods such as next, getString and getObject but it is quite easy to mock the rest by following the same pattern.
public class MockResultSet {
private final Map<String, Integer> columnIndices;
private final Object[][] data;
private int rowIndex;
private MockResultSet(final String[] columnNames,
final Object[][] data) {
// create a map of column name to column index
this.columnIndices = IntStream.range(0, columnNames.length)
.boxed()
.collect(Collectors.toMap(
k -> columnNames[k],
Function.identity(),
(a, b) ->
{ throw new RuntimeException("Duplicate column " + a); },
LinkedHashMap::new
));
this.data = data;
this.rowIndex = -1;
}
private ResultSet buildMock() throws SQLException {
final var rs = mock(ResultSet.class);
// mock rs.next()
doAnswer(invocation -> {
rowIndex++;
return rowIndex < data.length;
}).when(rs).next();
// mock rs.getString(columnName)
doAnswer(invocation -> {
final var columnName = invocation.getArgumentAt(0, String.class);
final var columnIndex = columnIndices.get(columnName);
return (String) data[rowIndex][columnIndex];
}).when(rs).getString(anyString());
// mock rs.getObject(columnIndex)
doAnswer(invocation -> {
final var index = invocation.getArgumentAt(0, Integer.class);
return data[rowIndex][index - 1];
}).when(rs).getObject(anyInt());
final var rsmd = mock(ResultSetMetaData.class);
// mock rsmd.getColumnCount()
doReturn(columnIndices.size()).when(rsmd).getColumnCount();
// mock rs.getMetaData()
doReturn(rsmd).when(rs).getMetaData();
return rs;
}
/**
* Creates the mock ResultSet.
*
* @param columnNames the names of the columns
* @param data
* @return a mocked ResultSet
* @throws SQLException
*/
public static ResultSet create(
final String[] columnNames,
final Object[][] data)
throws SQLException {
return new MockResultSet(columnNames, data).buildMock();
}
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.