质量保证
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
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 代码库的某些部分被集成测试覆盖的几率显着降低。
反馈
您对此页面有任何反馈吗? 我们很乐意听到您的意见!