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 ResultSet
s (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.