简体   繁体   English

包含 SQL 查询的方法的 JUnit 测试

[英]JUnit test for a method that contains SQL queries

I have an old Java project (no frameworks/build tools used) that has a class full of SQL methods and corresponding Bean-classes.我有一个旧的 Java 项目(没有使用框架/构建工具),它有一个充满 SQL 方法和相应 Bean 类的类。 The SQL methods mostly use SELECT, INSERT and UPDATE queries like this: 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();
        }
    }
}

What is the best practice in unit testing when it comes to SQL queries?当涉及到 SQL 查询时,单元测试的最佳实践是什么?

The easiest way I can think of, would be to use my development database;我能想到的最简单的方法是使用我的开发数据库; just call the sqlUpdateAge() in the test class, query the database for a result set and assertTrue that the set age is in the result set.只需在测试类中调用 sqlUpdateAge(),查询数据库中的结果集并 assertTrue 设置的年龄在结果集中。 However, this would fill up the development database with unnecessary data, and I would like to avoid that.但是,这会用不必要的数据填满开发数据库,​​我想避免这种情况。

Is the solution to create a so-called in-memory database or somehow rollback the changes I made?是创建所谓的内存数据库的解决方案还是以某种方式回滚我所做的更改?

If I need an in-memory database:如果我需要一个内存数据库:

  1. Where and how would I create it?我将在哪里以及如何创建它? Straight to the test class, or perhaps to a config file?直接到测试类,或者可能到配置文件?
  2. How do I pass it to the updateAge() method?我如何将它传递给 updateAge() 方法?

Things would have been easy with a Spring Boot project.有了 Spring Boot 项目,事情会很容易。 In your case, you have many strategies:在你的情况下,你有很多策略:

  1. Configure a H2 database.配置H2数据库。 You can initialize your database with the creation of a schema and insertion of data in a setUp method with the @BeforeEach annotation.您可以通过使用@BeforeEach注释在setUp方法中创建架构和插入数据来初始化您的数据库。
  2. You can use a dedicated framework like DbUnit .您可以使用像DbUnit这样的专用框架。
  3. You will have to initialize your dbConnection also in a setUp method in your unit test.您还必须在单元测试的setUp方法中初始化dbConnection

I would suggest to see if you can start with autmoating the build.我建议看看你是否可以从自动构建开始。 That is either by introducing a build tool such as maven or gradle - or if not possible - scipting the build.那是通过引入构建工具(例如 maven 或 gradle) - 或者如果不可能 - scipting 构建。 In any case, your goal should be to get to a point where it's easy for you to trigger a buil together with tests whenever code changes.无论如何,您的目标应该是在代码更改时轻松触发构建和测试。

If you are not able to produce a consistent build on every change with the guarantee that all unit tests have been run, then there's really no value in writing unit tests in the first place.如果您不能在保证所有单元测试都已运行的情况下对每个更改生成一致的构建,那么首先编写单元测试就真的没有价值。 That is because otherwise, your tests are going to fail eventually due to code modifications and you wouldn't notice unless all your tests are automatically run.那是因为否则,您的测试最终将因代码修改而失败,除非您的所有测试都自动运行,否则您不会注意到。

Once you have that, you might have some hints to how you would like to run unit or integration tests.一旦你有了它,你可能会有一些关于如何运行单元或集成测试的提示。

As you can't benefit from testing support that many application frameworks provide, you're basically left on your own for how to configure database testing setup.由于您无法从许多应用程序框架提供的测试支持中受益,因此您基本上可以自行决定如何配置数据库测试设置。 In that case, I don't think that an inmemory database is really the best opion, because:在那种情况下,我不认为内存数据库真的是最好的选择,因为:

  • It's a different database technology than what you are normally using, and as the code indicates you are not using an ORM that will take care of different SQL dialects for you.这是一种与您通常使用的数据库技术不同的数据库技术,并且正如代码所示,您没有使用 ORM 来处理不同的 SQL 方言。 As that's the case, you might find yourself in a position, where you are unable to accurately test your code because of SQL dialect differeces.在这种情况下,您可能会发现自己处于无法准确测试代码的位置,因为 SQL 方言差异。
  • You will need to do all the setup of the inmemory DB yourself - which is of course possible, but still it's a piece of code that you need to maintain and that can also fail.您需要自己完成内存数据库的所有设置 - 这当然是可能的,但它仍然是您需要维护的一段代码,并且也可能失败。

The two alternatives I can think of are:我能想到的两种选择是:

  • Use Docker to start your actual database technology for every time you run the tests.每次运行测试时,使用 Docker 启动您的实际数据库技术。 (that's also something you have to script for yourself, but it will most likely be a very simple and short command you need to execute) (这也是您必须为自己编写脚本的内容,但它很可能是您需要执行的一个非常简单且简短的命令)
  • have a test database running on your test environment that you use.在您使用的测试环境上运行一个测试数据库。 Every time before you run the tests, esure the database is reset to the original state.每次运行测试之前,请确保将数据库重置为原始状态。 (easiest way to do this is to drop the existing schema and restore to the original schema). (最简单的方法是删除现有架构并恢复到原始架构)。 In this case, you will need to ensure that you don't run multiple builds in parallell against the same test database.在这种情况下,您需要确保不会针对同一个测试数据库并行运行多个构建。

These suggestions apply only if you have experience on the shell and/or have support from someone in ops.这些建议仅适用于您有 shell 经验和/或得到操作人员支持的情况。 If not, setting up H2 might be easier and more straight forward.如果没有,设置 H2 可能更容易、更直接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM