VOOZH about

URL: https://www.javacodegeeks.com/2018/09/java-mocking-resultset-using-mockito.html

⇱ Java: Mocking a ResultSet using Mockito - Java Code Geeks


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.

Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Thank you!

We will contact you soon.

πŸ‘ Photo of Fahd Shariff
Fahd Shariff
September 10th, 2018Last Updated: September 10th, 2018
5 7,921 1 minute read

Fahd Shariff

Fahd is a software engineer working in the financial services industry. He is passionate about technology and specializes in Java application development in distributed environments.
Subscribe

This site uses Akismet to reduce spam. Learn how your comment data is processed.

5 Comments
Oldest
Newest Most Voted
Oscar MejΓ­a
5 years ago

Hey Thanks a lot!

0
Reply
amit
4 years ago

bhai how to use it in our project

0
Reply
Botond
2 years ago

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)

2
Reply
Marcus Voltolim
1 year ago
Reply to  Botond
 data[rowIndex][index - 1];
0
Reply
Marcus Voltolim
1 year ago

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 Β»

0
Reply
Back to top button
Close
wpDiscuz