Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing a method that takes a ResultSet as parameter

How does one go about unit testing an object that can't be instantiated? Because currently I have a method that converts a ResultSet to an object but I'm unsure if this violates any programming principles.

public CItem convert(ResultSet rs) {
    CItem ci = new CItem ();

    try {
        ci.setHinumber(rs.getString("id"));
        ci.setHostname(rs.getString("sysname"));
        ci.setOs(rs.getString("zos"));
        ci.setTenant(rs.getString("customer_name"));
        //ci.setInstallation(rs.getField("installation_name"));
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return ci;
}

Do I need to look for a different way to approach this solely because it can't be unit tested? Or can I somehow fake a ResultSet object.

Any help would be appreciated.

like image 366
DGK Avatar asked Jan 25 '17 16:01

DGK


People also ask

Which method of the ResultSet is used to determine whether a value?

The wasNull() method of the ResultSet interface determines whether the last column read had a Null value. i.e. whenever you read the contents of a column of the ResultSet using the getter methods (getInt(), getString etc...) you can determine whether it (column) contains null values, using the wasNull() method.

What are the methods of ResultSet interface?

The ResultSet interface provides getter methods ( getBoolean , getLong , and so on) for retrieving column values from the current row. Values can be retrieved using either the index number of the column or the name of the column. In general, using the column index will be more efficient. Columns are numbered from 1.

Which method of ResultSet is used to get data from a specific row?

The method ResultSet. insertRow inserts the contents of the insert row into the ResultSet object and into the database. Note: After inserting a row with the ResultSet. insertRow , you should move the cursor to a row other than the insert row.


2 Answers

You could simply mock your ResultSet to provide a value for each field and check that the result contains what you expect.

For example with Mockito, your test would be something like this:

@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {

    @Mock
    private ResultSet resultSet;

    @Test
    public void testConvert() throws SQLException {
        // Define the behavior of the mock for each getString method's call
        Mockito.when(resultSet.getString("id")).thenReturn("myId");
        Mockito.when(resultSet.getString("sysname")).thenReturn("myHost");
        Mockito.when(resultSet.getString("zos")).thenReturn("myOS");
        Mockito.when(resultSet.getString("customer_name")).thenReturn("myCustomerName");

        // Launch the method against your mock
        SomeClass someClass = new SomeClass();
        CItem item = someClass.convert(resultSet);

        // Check the result
        Assert.assertNotNull(item);
        Assert.assertEquals("myId", item.getHinumber());
        Assert.assertEquals("myHost", item.getHostname());
        Assert.assertEquals("myOS", item.getOs());
        Assert.assertEquals("myCustomerName", item.getTenant());
    }
}
like image 144
Nicolas Filotto Avatar answered Oct 05 '22 17:10

Nicolas Filotto


If your class does not deal with DB access, accepting a ResultSet as an argument feels like a code smell.

You can use a mocking framework like Mockito or Power Mock to create a mock ResultSet. However you should not mock such classes which you did not write (i.e. libraries/ JDK classes).

Suppose that your ResultSet represents some order data from an Order table. What this method really needs is 'order data' and you should not worry about how and where you get this data from at this point. So you should ideally define an interface like this.

interface OrderRepository {
    OrderData get();
}

Then you can have a class which implements this interface JDBCOrderRepository which deals with ResultSet. And your method ('convert') will now accept an OrderRepository instead of ResultSet. In order to test your method you mock OrderRepository instead of ResultSet which is easier.

Now how would you test JDBCOrderRepository? Well, probably you should test it with a running instance of DB which is in fact an integration test.

like image 39
Fahim Farook Avatar answered Oct 05 '22 17:10

Fahim Farook