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

资讯详情

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

Testcontainers Java 集成 TiDB:轻量级分布式数据库容器化测试实战指南

Testcontainers Java 集成 TiDB:轻量级分布式数据库容器化测试实战指南 Testcontainers Java 集成 TiDB轻量级分布式数据库容器化测试实战指南【免费下载链接】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 为 TiDB 提供了开箱即用的官方模块让开发者无需本地安装任何数据库即可在 JUnit 测试中一键拉起一个真实运行在 Docker 容器中的 TiDB 实例完成与生产环境高度一致的集成测试。本文将基于docs/modules/databases/tidb.md文档结合仓库内modules/tidb的源码与测试完整讲解该模块的依赖引入、容器启动、JDBC URL 自动装配以及底层实现细节帮助你快速把 TiDB 接入 Testcontainers 测试体系。TiDB 模块概览镜像、端口与类结构Testcontainers 的 TiDB 模块位于仓库 modules/tidb 目录核心代码由两个类构成TiDBContainer.java容器封装类继承自JdbcDatabaseContainerTiDBContainer负责端口暴露、启动等待策略、JDBC URL 构造与连接信息提供TiDBContainerProvider.java容器工厂类继承自JdbcDatabaseContainerProvider供 Testcontainers 的 JDBC URL 机制按需创建 TiDB 容器。从源码类注释TiDBContainer.java可以看到该模块的默认约定项目取值说明官方镜像pingcap/tidb由DOCKER_IMAGE_NAME常量定义数据库服务端口4000TiDB 的 MySQL 兼容协议监听端口HTTP 状态端口10080提供/status健康检查端点默认数据库名test源码中databaseName字段的初始值默认用户名root与 TiDB 默认行为一致默认密码空字符串无密码添加模块依赖在项目的pom.xml或build.gradle中加入testcontainers-tidb依赖即可版本号以你使用的 Testcontainers 版本为准即原文中的{{latest_version}}占位 Gradlegroovy testImplementation org.testcontainers:testcontainers-tidb:{{latest_version}} Mavenxml dependency groupIdorg.testcontainers/groupId artifactIdtestcontainers-tidb/artifactId version{{latest_version}}/version scopetest/scope /dependency重要提示引入该 Testcontainers 库 JAR 并不会自动引入数据库驱动 JAR。TiDB 兼容 MySQL 协议其 JDBC 驱动即 MySQL Connector/J你需要额外在项目中显式声明com.mysql:mysql-connector-j依赖否则运行时会出现驱动类找不到的异常。编程式启动 TiDB 容器最小可运行示例在任意 Java 应用中只需一行构造代码即可创建一个 TiDB 容器实例并启动TiDBContainer tidb new TiDBContainer(pingcap/tidb:v6.1.0); tidb.start(); // 执行测试逻辑 tidb.stop();仓库中的 TiDBContainerTest.java 给出了与 JUnit 5 结合的完整用法包括启动后的连通性验证Test void testSimple() throws SQLException { try ( // container { TiDBContainer tidb new TiDBContainer(pingcap/tidb:v6.1.0) // } ) { tidb.start(); ResultSet resultSet performQuery(tidb, SELECT 1); int resultSetInt resultSet.getInt(1); assertThat(resultSetInt).isEqualTo(1); assertHasCorrectExposedAndLivenessCheckPorts(tidb); } }该测试还验证了容器暴露的端口与存活检查端口完全一致均覆盖4000数据库端口与10080HTTP 状态端口两个端口private void assertHasCorrectExposedAndLivenessCheckPorts(TiDBContainer tidb) { Integer tidbPort 4000; Integer restApiPort 10080; assertThat(tidb.getExposedPorts()).containsExactlyInAnyOrder(tidbPort, restApiPort); assertThat(tidb.getLivenessCheckPortNumbers()) .containsExactlyInAnyOrder(tidb.getMappedPort(tidbPort), tidb.getMappedPort(restApiPort)); }结合 JUnit 的容器生命周期管理与所有 Testcontainers 数据库容器一样TiDB 模块同样支持经典的 JUnit 4Rule/ClassRule或 JUnit 5 的Testcontainers/Container注解管理方式使用Rule时每个测试方法获得独立容器使用ClassRule时整个测试类共享一个容器。容器启动后可通过以下方法获取连接信息tidb.getJdbcUrl()返回可直接用于建立连接的 JDBC URLtidb.getUsername()返回用户名TiDB 固定为roottidb.getPassword()返回密码TiDB 默认为空tidb.getMappedPort(4000)获取宿主机上映射到的实际端口。初始化脚本与 URL 参数仓库测试展示了两个进阶用法TiDBContainerTest.java使用类路径初始化脚本在容器启动后自动执行建表与数据初始化TiDB 与 MySQL 兼容因此可直接复用 MySQL 风格的 SQLTiDBContainer tidb new TiDBContainer(TiDBTestImages.TIDB_IMAGE) .withInitScript(somepath/init_tidb.sql);仓库中对应提供了 init_mysql.sql 作为此类脚本的示例CREATE TABLE bar ( foo VARCHAR(255) ); INSERT INTO bar (foo) VALUES (hello world);追加 JDBC URL 附加参数TiDBContainer tidb new TiDBContainer(TiDBTestImages.TIDB_IMAGE) .withUrlParam(sslmode, disable);该测试断言生成的 JDBC URL 中包含?与sslmodedisable说明withUrlParam会以正确的方式拼接进连接串。Testcontainers JDBC URL 自动装配如果不想在代码中显式管理容器可以直接把普通 JDBC 连接串改为 Testcontainers 的 URL 方案Testcontainers 会“魔法般”地自动创建并销毁容器jdbc:tc:tidb:v6.1.0:///databasename在jdbc:后插入tc:tidb是模块名由 TiDBContainer.java 中的NAME tidb常量定义v6.1.0是要使用的镜像 tag不指定时TiDBContainerProvider.java 默认使用v6.1.0///databasename中的主机、端口与数据库名都会被忽略可任意填写或保留。仓库中的 TiDBJDBCDriverTest.java 直接以该 URL 作为测试数据验证了这一机制public static IterableObject[] data() { return Arrays.asList( new Object[][] { { jdbc:tc:tidb://hostname/databasename, EnumSet.noneOf(Options.class) } } ); }配合 JDBC URL 的实用参数沿用通用 JDBC 支持详见 jdbc.mdTiDB 的jdbc:tc:URL 同样支持以下查询参数参数作用示例TC_INITSCRIPT容器启动后执行类路径上的初始化 SQLjdbc:tc:tidb:v6.1.0:///db?TC_INITSCRIPTsomepath/init_tidb.sqlTC_INITSCRIPTfile:从文件系统加载初始化脚本jdbc:tc:tidb:v6.1.0:///db?TC_INITSCRIPTfile:src/test/resources/init.sqlTC_INITFUNCTION调用自定义静态方法完成初始化如执行 Flyway/Liquibase 迁移jdbc:tc:tidb:v6.1.0:///db?TC_INITFUNCTIONcom.example.Init::initTC_DAEMONtrue以守护模式运行即使无活动连接容器也不停止jdbc:tc:tidb:v6.1.0:///db?TC_DAEMONtrueTC_TMPFS使用 tmpfs 内存挂载加速测试容器停止后数据丢失jdbc:tc:tidb:v6.1.0:///db?TC_TMPFS/testtmpfs:rw使用 URL 方式时无需手动实例化容器Testcontainers 会在连接建立前自动完成容器的创建、启动与就绪等待。源码级细节端口、等待策略与连接参数启动就绪等待策略TiDBContainer.java 的构造方法中配置了基于 HTTP 的就绪探测waitingFor( new HttpWaitStrategy() .forPath(/status) .forPort(REST_API_PORT) .forStatusCode(200) .withStartupTimeout(Duration.ofMinutes(1)) );即等待容器内10080端口的/status返回 HTTP 200超时上限为 1 分钟确保 TiDB 完全就绪后才把控制权交给测试代码。JDBC 驱动与连接 URL 的构造TiDB 兼容 MySQL 协议因此getDriverClassName()优先返回com.mysql.cj.jdbc.DriverMySQL Connector/J 8.x若类路径中只有旧版驱动则回退到com.mysql.jdbc.DriverTiDBContainer.java。getJdbcUrl()返回形如jdbc:mysql://host:mappedPort/test的连接串并自动追加通过withUrlParam设置的附加参数。更值得注意的是 constructUrlForConnection 方法它会自动为连接串补充两个对 MySQL 8 驱动至关重要的参数useSSLfalse关闭 SSL避免测试环境未配置证书时报错allowPublicKeyRetrievaltrue允许客户端在首次连接时获取服务器公钥规避Public Key Retrieval is not allowed的经典报错。这意味着即使你不显式配置任何 JDBC 参数模块也会生成一个开箱即用、不会因 SSL/密钥检索问题而失败的连接。不可修改的数据库名、用户名与密码TiDB 官方 Docker 镜像目前不支持在启动时自定义数据库名、用户名与密码因此 TiDBContainer.java 中对应的withDatabaseName(...)、withUsername(...)、withPassword(...)三个方法都会直接抛出UnsupportedOperationException。如需修改用户名密码只能通过withUrlParam等途径在连接串层面处理。getTestQueryString()返回SELECT 1这是 Testcontainers 用于校验连接有效性的探活 SQL。通用数据库容器能力TiDB 模块继承了所有关系型数据库容器共有的能力镜像名替换withImageSubstitute、日志输出getLogs()、文件复制、容器共享与重用reuse、资源限制设置等。完整的通用使用说明可参考 数据库容器文档其核心理念是与 H2 等内存数据库相比Testcontainers 提供的是 100% 真实数据库兼容性——容器内运行的是一套真实的 TiDB代价是启动性能稍逊于 H2与本地/虚拟机安装的数据库相比其优势在于每次测试都从干净的已知状态启动杜绝测试之间的数据污染。快速参考依赖坐标org.testcontainers:testcontainers-tidbtest scope镜像与默认 tagpingcap/tidb:v6.1.0数据库端口 / 状态端口4000/10080编程式启动new TiDBContainer(pingcap/tidb:v6.1.0)后调用start()JDBC URLjdbc:tc:tidb:v6.1.0:///databasename默认连接信息库名test、用户root、空密码就绪判定10080端口/status返回 200超时 1 分钟初始化 SQL 示例init_mysql.sql集成测试示例TiDBContainerTest.java、TiDBJDBCDriverTest.java【免费下载链接】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),仅供参考
返回列表