【问题标题】:How to throw SQLException in a DAO-layer如何在 DAO 层中抛出 SQLException
【发布时间】:2021-03-13 17:32:00
【问题描述】:

我想用 JUnit 测试 DAO 类。测试覆盖率为 80%,因此几乎每一行代码都被覆盖,除了 SQLException 的 catch 子句。我不知道如何引发 SQLException

 public void removeStudentFromCourse(Integer studentId, Integer courseId) {
        try (Connection connection = connector.getConnection();
             PreparedStatement statement = connection.prepareStatement(
                     DELETE_STUDENT_FROM_ONE_COURSE_QUERY)) {
            statement.setInt(1, studentId);
            statement.setInt(2, courseId);
            statement.executeUpdate();
        } catch (SQLException e) {
            throw new DBException("Can`t remove student with id: " + studentId +
                    " from course with id:" + courseId, e);
        }
    }

【问题讨论】:

  • 传递不存在的 studentId 怎么样?
  • 您好,您可以使用 Mockito。你有一个抛出异常的例子:baeldung.com/mockito-exceptions
  • @IKo 那将导致没有更新,而不是异常。
  • 根据 PreparedStatement docs.oracle.com/javase/7/docs/api/java/sql/… 的文档“SQLException - 如果发生数据库访问错误;在关闭的 PreparedStatement 上调用此方法或 SQL 语句返回 ResultSet 对象”。意味着您将不得不模拟您的连接器。正如@stacy 所说,您可以使用mockito 来做到这一点。您可以考虑的一件事是,如果您真的想在此处捕获 SQLException。因为只有当您遇到配置问题(例如错误的连接字符串)时才会发生这种情况。
  • 我认为在某些情况下测试 catch 部分可能是值得的(例如,检查我们是否正确处理异常,或者它们与 catch 块没有问题 - 你不会想要 NPE通过 SQLException :))。然而,OP 希望获得最佳覆盖率(据我了解,测试覆盖率为 80%,因此几乎每一行代码都被覆盖,除了 SQLException 的 catch 子句

标签: java code-coverage dao


【解决方案1】:

你必须作弊的地方:

  • 你的连接器对象(不管它是什么)是模拟的吗
  • 让模拟返回模拟的Connection
  • 让模拟的Connection 返回模拟的PreparedStatement
  • 通过抛出 SQLException 使模拟的 PreparedStatement 失败。

使用 mockito 这可能是:

// case 1
when(connector.getConnection()).thenThrow(SQLException.class); 
// case 2
Connection cnx = mock(Connection.class);
when(cnx.prepareStatement(anyString()).thenThrow(SQLException.class); 
when(connector.getConnection()).thenReturn(cnx);
when(connector.getConnection()).thenThrow(SQLException.class); 

【讨论】:

  • Mocking 是正确的方法,我同意 NoData 和 Stacky 推荐的 Mockito 来帮助你。
【解决方案2】:

你可以

  • 有一个连接会在调用 getConnection() 时抛出 SQLException
  • 有一个连接会产生一个模拟 PreparedStatement,它会在一个被调用的方法上抛出一个SqlException,例如setInt()executeUpdate(),或者
  • DELETE_STUDENT_FROM_ONE_COURSE_QUERY 覆盖为无效的SQL 语句。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 2012-08-12
    • 2010-11-26
    • 2014-03-30
    • 2015-11-23
    相关资源
    最近更新 更多