Core Java
Java: Mocking a ResultSet using Mockito
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();
}
}| Published on Java Code Geeks with permission by Fahd Shariff, partner at our JCG program. See the original article here: Java: Mocking a ResultSet using Mockito Opinions expressed by Java Code Geeks contributors are their own. |


Hey Thanks a lot!
bhai how to use it in our project
I think that this implementation missed that ResultSet implementations should follow the contract that column indexes start from 1 and not 0, see:
https://docs.oracle.com/en/java/javase/17/docs/api/java.sql/java/sql/ResultSet.html#getObject(int)
More simple implementation! import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.List; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class MockResultSet { private final List<String> columnNames; private final Object[][] data; private int rowIndex; private MockResultSet(final List<String> columnNames, final Object[][] data) { this.columnNames = columnNames; this.data = data; this.rowIndex = -1; } private ResultSet buildMock() throws SQLException { final var resultSet = mock(ResultSet.class); // mock resultSet.next() when(resultSet.next()) .thenAnswer(invocation -> { rowIndex++; return rowIndex < data.length; }); // mock resultSet.getObject(columnName) when(resultSet.getObject(anyString())) .thenAnswer(invocation -> { final var columnName = invocation.getArgument(0, String.class); final var columnIndex = columnNames.indexOf(columnName); return data[rowIndex][columnIndex];… Read more »