Search code examples
junitmockitosqlexception

How to force a SQLException in JUnit


I'm writing unit tests in JUnit, but have not been able to successfully cover a branch of a particular method that catches a SQLException and returns a null object. This is the class I'm testing:

@Component
public class UnitOfMeasureRowMapper implements RowMapper<UnitOfMeasure> {
    public UnitOfMeasure mapRow(final ResultSet resultSet, final int rowNumber) throws SQLException {
        UnitOfMeasure unitOfMeasure = new UnitOfMeasure();
        try {
            unitOfMeasure.setUnitOfMeasureId(resultSet.getInt("UNITOFMEASUREID"));
            unitOfMeasure.setOwnerUserId(resultSet.getInt("USERID"));
            unitOfMeasure.setName(resultSet.getString("NAME"));
            unitOfMeasure.setDescription(resultSet.getString("DESCRIPTION"));
        } catch (SQLException e) {
            unitOfMeasure = null;
        }
        return unitOfMeasure;
    }
}

This is the JUnit test that I have written to cover the second branch of the above method (with appropriate context from the test class):

private static UnitOfMeasure testUnitOfMeasure;
    private static UnitOfMeasureRowMapper mockRowMapper;

    public void setUp() throws Exception {
        mockRowMapper = mock(UnitOfMeasureRowMapper.class);
        mockResultSet = mock(ResultSet.class);
    }
    @Test(expected=SQLException.class)
    public void testUnitOfMeasureRowMapperFailsSQLException() throws SQLException {

        when(mockRowMapper.mapRow(mockResultSet, 1)).thenReturn(null);
        testUnitOfMeasure = mockRowMapper.mapRow(mockResultSet, 1);
    }

I think the problem is with the last line; somehow I need to force a SQLException. The problem is, I don't know how and haven't been able to find an answer. Can anyone help?


Solution

  • If I understand the question well, the class under test is UnitOfMeasureRowMapper. If this is true, then you don't want to mock it in your test, otherwise you are testing a mock! What is under test in your JUnit, is the behavior of UnitOfMeasureRowMapper#mapRow when ResultSet you give it throws a SQLException during the execution of the method. Then you want this method to return null. I would write it like this:

    private ResultSet mockResultSet;
    private RowMapper<UnitOfMeasure> rowMapper = new UnitOfMeasureRowMapper();
    
    public void setUp() throws Exception {
        mockResultSet = mock(ResultSet.class);
    }
    @Test
    public void mapRow_SHOULD_return_null_WHEN_resultSet_throws_a_SQLException() {
        when(mockResultSet.getInt(anyString()).thenThrow(new SQLException());
        assertThat(mockRowMapper.mapRow(mockResultSet, 1), nullValue());
    }
    

    As suggested Samuel in his answer, you may set one of the method of the result set you use to throw a SQLException, and then check in your JUnit that the mapRow method returns null as expected. Here you are not testing the behavior of the result set, so its fine to mock it to achieve a behavior it would normally have under some circunstancies that would be painful to obtain otherwise. Mocking the result set behavior lets you focus on testing the RowMapper behavior.

    You are testing the UnitOfMeasureRowMapper that implements RowMapper. So have a rowMapper property in your JUnit, and I prefer to see it through its interface. I like to brutally call the constructor of UnitOfMeasureRowMapper because I want to keep my JUnit as simple as they can be.