使用 jOOQ 对大型 SELECT 查询进行单元测试

Unit test for a large SELECT query with jOOQ

我正在使用 jOOQ 来处理关系数据库。我有一个 SELECT 查询,我需要为其编写带有模拟的单元测试。基于 this doc and 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 语句,它从多个 table 连接中选择 30 多个列。好像和

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

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

感谢任何帮助。

回答您的问题

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

Higher-degree records

jOOQ chose to explicitly support degrees up to 22 to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety.

您仍然可以使用 DSLContext.newRecord(Field...). Now, there is no values(Object...) method on the Record type, because the Record type is the super type of all the Record1 - Record22 types. If such an overload were present, then the type safety on the sub types would be lost, because the values(Object...) method is applicable for all types of arguments. This might be fixed in the future by introducing a new RecordN subtype.

构造包含超过 22 个字段的记录

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

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

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

免责声明:

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

Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

看来您要重新实现一个数据库,它可以“运行”任何类型的查询,包括具有 23+ 列的查询,并且每次您更改被测查询时,您也会在这里更改此测试。我仍然建议您使用 testcontainers or even with H2, which will help cover many more queries than any such unit test approach. Here's a quick example showing how to do that: https://github.com/jOOQ/jOOQ/tree/main/jOOQ-examples/jOOQ-testcontainers-example

进行集成测试

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