【问题标题】:JUnit test for a method that contains SQL queries包含 SQL 查询的方法的 JUnit 测试
【发布时间】:2021-12-23 05:56:57
【问题描述】:

我有一个旧的 Java 项目(没有使用框架/构建工具),它有一个包含 SQL 方法和相应 Bean 类的类。 SQL 方法大多使用这样的 SELECT、INSERT 和 UPDATE 查询:

public static void sqlUpdateAge(Connection dbConnection, int age, int id) {

    PreparedStatement s = null;
    ResultSet r = null;

    String sql = "UPDATE person SET age = ? WHERE id = ?";

    try {
        s = dbConnection.prepareStatement(sql);
        s.setInt(1, age);
        s.setInt(2, id);
        s.addBatch();
        s.executeBatch();

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (r != null)
                r.close();
            if (s != null)
                s.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

在 SQL 查询方面,单元测试的最佳实践是什么?

我能想到的最简单的方法是使用我的开发数据库;只需在测试类中调用 sqlUpdateAge(),在数据库中查询结果集并断言设置的年龄在结果集中。但是,这会使开发数据库充满不必要的数据,我想避免这种情况。

解决方案是创建所谓的内存数据库还是以某种方式回滚我所做的更改?

如果我需要一个内存数据库:

  1. 我将在哪里以及如何创建它?直接到测试类,或者配置文件?
  2. 如何将它传递给 updateAge() 方法?

【问题讨论】:

    标签: java sql unit-testing junit h2


    【解决方案1】:

    有了 Spring Boot 项目,事情就变得简单了。在你的情况下,你有很多策略:

    1. 配置H2 数据库。您可以使用 @BeforeEach 注释在 setUp 方法中创建架构并插入数据来初始化数据库。
    2. 您可以使用像DbUnit 这样的专用框架。
    3. 您还必须在单元测试的 setUp 方法中初始化您的 dbConnection

    【讨论】:

      【解决方案2】:

      我建议您看看是否可以从自动构建开始。这可以通过引入诸如 maven 或 gradle 之类的构建工具 - 或者如果不可能 - 对构建进行脚本化。在任何情况下,您的目标都应该是在代码更改时轻松触发构建和测试。

      如果您无法在每次更改时生成一致的构建并保证所有单元测试都已运行,那么首先编写单元测试真的没有任何价值。那是因为否则,您的测试最终会由于代码修改而失败,除非您的所有测试都自动运行,否则您不会注意到。

      一旦你有了这些,你可能会得到一些关于你希望如何运行单元测试或集成测试的提示。

      由于您无法从许多应用程序框架提供的测试支持中受益,因此您基本上只能靠自己来了解如何配置数据库测试设置。在那种情况下,我认为内存数据库并不是最好的选择,因为:

      • 这是一种与您通常使用的不同的数据库技术,并且正如代码所示,您没有使用会为您处理不同 SQL 方言的 ORM。在这种情况下,您可能会发现自己处于由于 SQL 方言差异而无法准确测试代码的位置。
      • 您需要自己完成内存 DB 的所有设置 - 这当然是可能的,但它仍然是您需要维护的一段代码,也可能会失败。

      我能想到的两种选择是:

      • 每次运行测试时,使用 Docker 启动实际的数据库技术。 (这也是您必须为自己编写的脚本,但它很可能是您需要执行的一个非常简单且简短的命令)
      • 在您使用的测试环境中运行一个测试数据库。每次运行测试之前,请确保将数据库重置为原始状态。 (最简单的方法是删除现有模式并恢复到原始模式)。在这种情况下,您需要确保不会针对同一个测试数据库并行运行多个构建。

      这些建议仅适用于您有外壳方面的经验和/或得到运营人员支持的情况。如果没有,设置 H2 可能会更容易、更直接。

      【讨论】:

      • 感谢您的评论!我对shell没有那么经验,所以我想我选择了H2。另外,我在这个项目中安装了 Maven。我现在是否使用 Maven 从命令提示符将 jar 包编译为 mvn 包,而不是从 IDE“导出 Jar”?
      • 嘿,是的,您将使用 mvn(例如 mvn 包)创建您的工件。但是,这不会将所有项目依赖项放入该 jar 中。如果您使用诸如“创建可运行 jar”或“创建 uber jar”之类的 IDE 功能 - mvn 包不会为您做这些。如果这就是您要寻找的,请搜索 maven shade 插件。 (你会在网上找到很多例子)
      猜你喜欢
      • 2017-09-30
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 1970-01-01
      相关资源
      最近更新 更多