【问题标题】:Unit test for a large SELECT query with jOOQ使用 jOOQ 对大型 SELECT 查询进行单元测试
【发布时间】:2021-05-16 23:32:54
【问题描述】:

我正在使用jOOQ 来处理关系数据库。我有一个SELECT 查询,我需要为它编写带有模拟的单元测试。基于this doc 和this post,我需要定义自己的数据提供者,它应该看起来像这样:

class MyProvider implements MockDataProvider {

    DSLContext create = DSL.using(SQLDialect.MYSQL);

    @Override
    public MockResult[] execute(MockExecuteContext mockExecuteContext) throws SQLException {
        MockResult[] mock = new MockResult[1];
        String sql = mockExecuteContext.sql();

        if (sql.startsWith("select")) {
            Result<Record2<String, String>> result = create.newResult(COL_1, COL_2);
            result.add(create.newRecord(COL_1, COL_2)
                             .values("val1", "val2"));

            mock[0] = new MockResult(1, result);
        }

        return mock;
    }
}

其中COL_1COL_2定义如下:

Field<String> COL_1 = field("Column1", String.class);
Field<String> COL_2 = field("Column2", String.class);

SELECT 很小(如上例中,只有 2 列)时,这非常简单明了。我想知道在复杂和大选择的情况下应该如何完成。例如,我有一个 SELECT 语句,它从多个表连接中选择 30 多个列。似乎与

相同的方法
Result<Record_X<String, ...>> result = create.newResult(COL_1, ...);
result.add(create.newRecord(COL_1, ...)
                 .values("val1", ...));

在超过 22 列的情况下不起作用。

感谢任何帮助。

【问题讨论】:

    标签: java jooq


    【解决方案1】:

    回答您的问题

    没有这样的限制,最多 22 列。 As documented here:

    更高学位记录

    jOOQ 选择显式支持高达 22 的度数,以匹配 Scala 的类型安全元组、函数和产品支持。然而,与 Scala 不同的是,jOOQ 还支持更高的度数,而无需额外的类型安全。

    您仍然可以使用DSLContext.newRecord(Field...) 构造包含超过 22 个字段的记录。现在,Record 类型上没有values(Object...) 方法,因为Record 类型是所有Record1 - Record22 类型的超类型。如果存在这样的重载,则子类型的类型安全性将丢失,因为values(Object...) 方法适用于所有类型的参数。将来可能会通过引入new RecordN subtype 来解决此问题。

    但是您可以通过其他方式将数据加载到您的记录中,例如致电Record.fromArray(Object...):

    Record record = create.newRecord(COL_1, ...);
    record.fromArray("val1", ...);
    result.add(record);
    

    values() 方法只是为fromArray() 提供便利(添加类型安全)。

    免责声明:

    我假设您已阅读所链接文档页面上的免责声明。无论如何,我还是在这里为这个问题的其他读者发布它,他们可能没有阅读免责声明:

    免责声明:使用此 jOOQ API 模拟 JDBC 连接的一般想法是使用非常简单的 JDBC 抽象来提供快速解决方法、注入点等。 不推荐使用这个模拟 API 模拟整个数据库(包括复杂的状态转换、事务、锁定等)。一旦您有此要求,请考虑使用实际数据库代替集成测试,而不是在 MockDataProvider 内实现您的测试数据库。

    看来您要重新实现一个可以“运行”任何类型查询的数据库,包括具有 23 列以上的查询,并且每次更改被测查询时,您也将在此处更改此测试.我仍然建议您改为使用 testcontainers 甚至使用 H2 进行集成测试,这将有助于覆盖比任何此类单元测试方法更多的查询。下面是一个快速示例,展示了如何做到这一点:https://github.com/jOOQ/jOOQ/tree/main/jOOQ-examples/jOOQ-testcontainers-example

    此外,集成测试将有助于测试查询的正确性。像这样的单元测试只会提供虚拟结果,而与实际查询无关。与 SQL 级别相比,此类模拟可能更容易在更高级别上实现,即通过模拟 DAO、存储库或任何方法来代替。

    【讨论】:

      猜你喜欢
      • 2018-07-06
      • 2016-05-30
      • 1970-01-01
      • 2015-03-23
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多