可用版本:Dev (3.21) | 最新版本 (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11

质量保证

适用于 ✅ 开源版   ✅ 专业版   ✅ 企业版

jOOQ 正在运行您最关键的逻辑:Java / Scala 应用程序和数据库之间的接口层。您可能出于以下任何原因选择了 jOOQ

  • 为了避免 JDBC 因字符串连接和基于索引的变量绑定而导致的冗长和易出错
  • 为您的内联 SQL 添加大量类型安全
  • 在使用您最喜欢的 IDE 的自动完成功能编写内联 SQL 时提高生产力

由于 jOOQ 位于您的应用程序的核心,因此您需要确保可以信任 jOOQ。这就是为什么 jOOQ 经过了大量的单元和集成测试,并非常注重集成测试

单元测试

单元测试是针对使用模拟的虚拟 JDBC 接口执行的,包括我们自己的 JDBC 模拟抽象。这些测试验证了各种 org.jooq.QueryPart 实现是否正确呈现 SQL 并正确绑定变量。

除了上述之外,众多类型的单元测试还包括

  • SQL 格式化测试
  • JSON 和 XML 数据导入/导出测试
  • 解析器测试
  • 映射器和转换器测试
  • SPI 测试
  • SQL 转换测试
  • 以及更多

集成测试

这是 jOOQ 测试套件中最重要的部分。目前针对标准集成测试数据库运行 10k+ 个查询,我们为此使用 testcontainers 和其他虚拟化实用程序。测试数据库和查询都被翻译成 30 多种受支持的 SQL 方言中的每一种,以确保不太可能将回归引入代码库中。

对于像 jOOQ 这样的库,集成测试比单元测试更具表现力,因为 SQL 方言中存在许多细微的差异。简单的模拟无法提供与实际数据库实例一样多的反馈。

jOOQ 集成测试运行最奇怪和最不真实的查询。作为这些广泛的集成测试套件的副作用,已经发现了 JDBC 驱动程序和/或开源数据库的许多极端情况错误,通过 jOOQ 提交了功能请求,并主要报告给 Derby、H2、HSQLDB。

代码生成测试

对于 30 多种受支持的集成测试数据库中的每一种,都会生成源代码,并且可以发现生成的源代码中的微小差异。如果生成的源代码中出现编译错误,则会添加新的测试表/视图/列,以避免此领域中的回归。

API 可用性测试和概念验证

jOOQ 在 jOOQ-meta 中用作概念验证。这包括复杂的查询,例如以下 Postgres 查询

Routines r1 = ROUTINES.as("r1");
Routines r2 = ROUTINES.as("r2");

for (Record record : create.select(
        r1.ROUTINE_SCHEMA,
        r1.ROUTINE_NAME,
        r1.SPECIFIC_NAME,

        // Ignore the data type when there is at least one out parameter
        DSL.when(exists(
                selectOne()
                .from(PARAMETERS)
                .where(PARAMETERS.SPECIFIC_SCHEMA.eq(r1.SPECIFIC_SCHEMA))
                .and(PARAMETERS.SPECIFIC_NAME.eq(r1.SPECIFIC_NAME))
                .and(upper(PARAMETERS.PARAMETER_MODE).ne("IN"))),
                    val("void"))
           .else_(r1.DATA_TYPE).as("data_type"),
        r1.CHARACTER_MAXIMUM_LENGTH,
        r1.NUMERIC_PRECISION,
        r1.NUMERIC_SCALE,
        r1.TYPE_UDT_NAME,

        // Calculate overload index if applicable
        DSL.when(
            exists(
                selectOne()
                .from(r2)
                .where(r2.ROUTINE_SCHEMA.in(getInputSchemata()))
                .and(r2.ROUTINE_SCHEMA.eq(r1.ROUTINE_SCHEMA))
                .and(r2.ROUTINE_NAME.eq(r1.ROUTINE_NAME))
                .and(r2.SPECIFIC_NAME.ne(r1.SPECIFIC_NAME))),
            select(count())
                .from(r2)
                .where(r2.ROUTINE_SCHEMA.in(getInputSchemata()))
                .and(r2.ROUTINE_SCHEMA.eq(r1.ROUTINE_SCHEMA))
                .and(r2.ROUTINE_NAME.eq(r1.ROUTINE_NAME))
                .and(r2.SPECIFIC_NAME.le(r1.SPECIFIC_NAME)).asField())
        .as("overload"))
    .from(r1)
    .where(r1.ROUTINE_SCHEMA.in(getInputSchemata()))
    .orderBy(
        r1.ROUTINE_SCHEMA.asc(),
        r1.ROUTINE_NAME.asc())
    .fetch()) {

    result.add(new PostgresRoutineDefinition(this, record));
}

与集成测试套件中相当简单且通常不真实的查询相比,这些相当复杂的查询表明 jOOQ API 适用于高级 SQL 用例。

清晰的 API 和实现。代码保持 DRY

作为整个 jOOQ 代码中的一般经验法则,一切都保持 DRY。一些例子

  • 整个代码库中只有一个地方可以从 JDBC ResultSet 中获取值
  • 整个代码库中只有一个地方可以将 jOOQ Records 转换为自定义 POJO

保持 DRY 会导致更长的堆栈跟踪,但反过来也会增加高度可重用代码块的相关性。jOOQ 代码库的某些部分被集成测试覆盖的几率显着降低。

反馈

您对此页面有任何反馈吗? 我们很乐意听到您的意见!

The jOOQ Logo