如何在JUnit中强制执行SQLException

时间:2012-09-29 00:59:40

标签: junit mockito sqlexception

我正在JUnit中编写单元测试,但是无法成功覆盖捕获SQLException并返回null对象的特定方法的分支。 这是我正在测试的课程:

@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;
    }
}

这是我编写的JUnit测试,用于覆盖上述方法的第二个分支(具有来自测试类的适当上下文):

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);
    }

我认为问题出在最后一行;不知怎的,我需要强制一个SQLException。问题是,我不知道怎么也找不到答案。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:4)

如果我理解这个问题,那么被测试的课程是 UnitOfMeasureRowMapper 。如果这是真的,那么你不想在你的测试中模拟它,否则你正在测试一个模拟! 在你的JUnit中测试的是 UnitOfMeasureRowMapper#mapRow 的行为,当你给它 ResultSet 时,它会在方法执行期间抛出一个SQLException。然后,您希望此方法返回null。 我会这样写:

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());
}

正如Samuel在他的回答中所建议的那样,你可以设置一个用于抛出SQLException的结果集的方法,然后在你的JUnit中检查mapRow方法是否按预期返回null。在这里,你没有测试结果集的行为,因此可以嘲笑它以实现在某些环境下通常会产生的行为,否则会很痛苦。模拟结果集行为使您可以专注于测试RowMapper行为。

您正在测试实现 RowMapper UnitOfMeasureRowMapper 。所以在你的JUnit中有一个 rowMapper 属性,我更喜欢通过它的界面看到它。我喜欢粗暴地调用 UnitOfMeasureRowMapper 的构造函数,因为我想保持我的JUnit尽可能简单。

答案 1 :(得分:0)

设置模拟getInt的方法之一(可能ResultSet?)以抛出异常。你没有指定你正在使用的模拟框架,所以我无法告诉你确切的语法。