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.
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.
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.
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.
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());
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With