十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Testcontainers Java 集成 YugabyteDB:YSQL 与 YCQL 双 API 容器化测试实战

Testcontainers Java 集成 YugabyteDB:YSQL 与 YCQL 双 API 容器化测试实战 Testcontainers Java 集成 YugabyteDBYSQL 与 YCQL 双 API 容器化测试实战【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-javaTestcontainers 的 YugabyteDB 模块testcontainers-yugabytedb为 Java 测试提供轻量级、可随时销毁的 YugabyteDB 数据库实例支持其两大访问 API基于 PostgreSQL 的完全关系型 APIYSQL与源于 Cassandra Query Language 的半关系型 SQL APIYCQL。阅读本文后你将掌握如何在 JUnit 测试中一键拉起 YugabyteDB 容器、通过 JDBC 或 DataStax 驱动直连访问、自定义数据库/角色/Keyspace、执行初始化脚本并理解其底层等待策略与端口映射原理。本文以 YugabyteDB Module 文档 为骨架并结合本仓库modules/yugabytedb模块的源码与测试进行深化。YugabyteDB 模块概览一种数据库两套 APIYugabyteDB 是一个同时对外提供两种查询接口的分布式数据库Testcontainers 模块为这两种接口分别封装了专用的容器类YSQLYugabyte Structured Query Language完全关系型 API由 PostgreSQL 代码构建兼容 PostgreSQL 的 SQL 语义与生态工具适合需要强事务、复杂 JOIN 与标准 SQL 的场景YCQLYugabyte Cloud Query Language半关系型 SQL API其根源于 Cassandra Query LanguageCQL使用 Keyspace、Table 等 CQL 概念适合高吞吐、宽表模型与 Cassandra 风格的应用。对应地仓库在modules/yugabytedb/src/main/java/org/testcontainers/containers/下提供了两个容器实现YugabyteDBYSQLContainer.java继承JdbcDatabaseContainer面向 YSQL/JDBC 生态YugabyteDBYCQLContainer.java继承GenericContainer面向 YCQL/CQL 生态。它们均基于官方镜像yugabytedb/yugabyte并以bin/yugabyted start --backgroundfalse作为启动入口。添加模块依赖在pom.xml或build.gradle中添加以下依赖// Gradle testImplementation org.testcontainers:testcontainers-yugabytedb:{{latest_version}}!-- Maven -- dependency groupIdorg.testcontainers/groupId artifactIdtestcontainers-yugabytedb/artifactId version{{latest_version}}/version scopetest/scope /dependency重要提示添加 Testcontainers 库 JAR 并不会自动引入 YugabyteDB 的驱动 JAR。如果计划在测试中真正连接数据库还需要在项目中显式加入对应驱动依赖——YSQL 使用 YugabyteDB JDBC 驱动com.yugabyte.DriverYCQL 使用 YCQL 客户端驱动如 DataStax Java Driver即本仓库 YCQL 测试中使用的com.datastax.oss:java-driver-core。YSQL API 使用JDBC 方式启动容器基本用法在 JUnit 测试中只需一行构造即可启动 YSQL 容器参考测试 YugabyteDBYSQLTest.javatry ( // creatingYSQLContainer { final YugabyteDBYSQLContainer ysqlContainer new YugabyteDBYSQLContainer( yugabytedb/yugabyte:2.14.4.0-b26 ) // } ) { ysqlContainer.start(); // 通过 JDBC 执行查询 assertThat(performQuery(ysqlContainer, SELECT 1).getInt(1)).isEqualTo(1); }容器启动后默认暴露以下端口见 YugabyteDBYSQLContainer.java端口用途5433YSQL 查询端口客户端连接7000Master 节点仪表盘9000Tserver 节点仪表盘默认凭据与库名均为yugabytedatabaseyugabyte、usernameyugabyte、passwordyugabyte。容器在configure()阶段通过环境变量YSQL_DB、YSQL_USER、YSQL_PASSWORD将这些值注入镜像从而在启动时创建对应的数据库与用户角色。自定义数据库、用户与认证模块支持通过链式调用定制初始对象与测试用例testCustomDatabase、testWithCustomRole一一对应final YugabyteDBYSQLContainer ysqlContainer new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) .withDatabaseName(yugabyte) .withPassword(yugabyte) .withUsername(yugabyte);withDatabaseName(...)指定初始化时创建的数据库名withUsername(...)指定自定义用户角色名withPassword(...)与withUsername搭配使用启用认证源码注释明确说明设置该参数即开启认证。这些值最终会通过环境变量传递给容器因此容器内新建的数据库/角色会与实际使用的 JDBC 连接保持一致。追加 JDBC URL 参数测试testWithAdditionalUrlParamInJdbcUrl演示了如何向生成的 JDBC URL 追加任意参数final YugabyteDBYSQLContainer ysqlContainer new YugabyteDBYSQLContainer(YBDB_TEST_IMAGE) .withUrlParam(sslmode, disable) .withUrlParam(application_name, yugabyte);生成后的getJdbcUrl()形如jdbc:yugabytedb://host:mappedPort/yugabyte?sslmodedisableapplication_nameyugabyte多个参数以连接可用于关闭 SSL、设置应用名等连接级配置。YSQL JDBC URL 速查容器对外提供的 JDBC URL 前缀为jdbc:yugabytedb驱动类为com.yugabyte.Driver健康检查查询为SELECT 1。在直接编码获取连接时可使用jdbc:yugabytedb://host:映射端口/database?useryugabytepasswordyugabyteTestcontainers JDBC URL一行声明即启动容器除了编程式构造容器本模块还支持 Testcontainers 的JDBC URL 魔法——通过在 JDBC URL 中嵌入tc:标记Testcontainers 会自动启动对应容器jdbc:tc:yugabyte:2.14.4.0-b26:///databasename其中tcTestcontainers JDBC 代理的保留关键字表示“自动启动容器”yugabyte数据库类型标识由 YugabyteDBYSQLContainerProvider.java 的supports(yugabyte)注册2.14.4.0-b26镜像标签默认标签未指定时使用该版本databasename容器内数据库名。Provider 还会从 URL 中解析user、password查询参数作为连接凭据测试 YugabyteDBYSQLJDBCDriverTest.java 中即使用了形如jdbc:tc:yugabyte://hostname/yugabyte?useryugabytepasswordyugabyte的 URL 完成驱动级连通性验证。更多关于 JDBC URL 机制的通用说明参见 JDBC 容器文档。YCQL API 使用CQL 方式启动容器基本用法YCQL 容器使用YugabyteDBYCQLContainer并搭配 DataStax Java Driver 建立 CqlSession参考测试 YugabyteDBYCQLTest.javatry ( // creatingYCQLContainer { final YugabyteDBYCQLContainer ycqlContainer new YugabyteDBYCQLContainer( yugabytedb/yugabyte:2.14.4.0-b26 ) .withUsername(cassandra) .withPassword(cassandra) // } ) { ycqlContainer.start(); // 通过 CqlSession 执行 CQL assertThat(performQuery(ycqlContainer, SELECT release_version FROM system.local).wasApplied()).isTrue(); }YCQL 容器的默认端口为9042见 YugabyteDBYCQLContainer.java同时同样暴露 7000/9000 仪表盘端口。由于 YCQL 不是 JDBC 体系容器类提供了一组面向 CQL 驱动的辅助方法getContactPoint()返回InetSocketAddresshost 映射后的 9042 端口用于CqlSession的addContactPoint(...)getLocalDc()返回本地数据中心名datacenter1用于withLocalDatacenter(...)getUsername()/getPassword()/getKeyspace()用于构造withAuthCredentials(...)与withKeyspace(...)。自定义 Keyspace 与认证YCQL 侧以 Keyspace 取代 Database 概念final YugabyteDBYCQLContainer ycqlContainer new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) .withKeyspaceName(random) // 自定义 Keyspace .withUsername(cassandra) // 自定义角色 .withPassword(cassandra); // 配合启用认证测试testCustomKeyspace验证了自定义 Keyspace 会被实际创建通过查询system_schema.keyspaces断言testAuthenticationEnabled则验证了自定义角色可成功登录system_auth.roles。容器通过环境变量YCQL_KEYSPACE、YCQL_USER、YCQL_PASSWORD将这些定制项注入镜像。初始化脚本Init Script与 JDBC 系列容器类似YCQL 容器支持withInitScript(...)在容器启动完成后执行 SQL 脚本final YugabyteDBYCQLContainer ycqlContainer new YugabyteDBYCQLContainer(YBDB_TEST_IMAGE) .withKeyspaceName(key) .withUsername(key) .withPassword(key) .withInitScript(init/init_yql.sql);其底层实现YugabyteDBYCQLContainer.java在containerIsStarted回调中通过ScriptUtils.runInitScript(new YugabyteDBYCQLDelegate(this), initScript)执行脚本。而 YugabyteDBYCQLDelegate.java 则调用容器内置的ycqlshCLI/home/yugabyte/tserver/bin/ycqlsh一次性执行全部语句并将多语句以分号拼接。测试testInitScript中的脚本创建了dsql表并写入greet Hello DSQL随后通过查询断言数据可读。对于更复杂的 schema 变更源码注释建议使用 Liquibase 等迁移框架管理此功能主要服务于无法引入迁移框架的独立服务。底层实现自定义等待策略如何保证“真的就绪”YugabyteDB 容器并没有使用简单的端口探测等待而是实现了两条定制等待策略原因是自定义数据库/角色/Keyspace 的创建是异步执行的端口可连接并不代表定制对象已经就绪。YSQL 等待策略YugabyteDBYSQLWaitStrategy.java在startupTimeout默认 60 秒见 YSQL 容器构造函数内不断重试执行冒烟 SQL——CREATE TABLE IF NOT EXISTS YB_SAMPLE(...)后立即DROP TABLE IF EXISTS YB_SAMPLE。只有建表成功才认为容器完全就绪因为该操作依赖容器内部正在初始化的自定义库/角色。测试testWaitStrategy专门断言了启动后该探测表已被清理、不存在于pg_tables中。YCQL 等待策略YugabyteDBYCQLWaitStrategy.java通过execInContainer在容器内执行ycqlsh containerIP -u user -p password -k keyspace -e SELECT release_version FROM system.local只有退出码为 0 才认为容器就绪。注意它使用容器网络接口 IP 而非 localhost 发起连接测试shouldStartWhenContainerIpIsUsedInWaitStrategy正是为此场景设计的回归用例。这两条策略让container.start()返回时数据库不仅“端口可连”而且“查询可用、定制对象已生效”从而避免测试中出现偶发的竞态失败。小结Testcontainers 的 YugabyteDB 模块用两个容器类优雅地覆盖了 YugabyteDB 的双 API 体系YSQLYugabyteDBYSQLContainer融入标准JdbcDatabaseContainer生态支持jdbc:tc:yugabyte:2.14.4.0-b26:///databasename这种零编码的 JDBC 自动容器化方案适用于 PostgreSQL 兼容的关系型应用YCQLYugabyteDBYCQLContainer面向 DataStax/CQL 客户端提供 Keyspace、认证、初始化脚本与 ContactPoint 等 CQL 原生能力适用于 Cassandra 风格的高吞吐应用。无论选择哪一套 API两条自定义等待策略都保证了容器启动语义的确定性。更完整的通用能力资源回收、镜像名替换、日志输出等可参考 数据库容器通用文档源码与测试均可从本仓库modules/yugabytedb目录直接研读。【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-java创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表