是否可创建指向多个MariaDB数据库的Testcontainer适配Quarkus多数据源测试
问题根因
你当前的代码写法存在逻辑错误:同一个MariaDBContainer实例多次调用withDatabaseName、withUsername、withPassword方法时,后配置的参数会直接覆盖之前的参数,最终容器启动后只会初始化1个名为SECOND_DB_NAME的数据库,因此测试时只能连接到一个数据源。
解决方案
方案一:启动两个独立的MariaDB容器实例(推荐,和生产多数据源场景匹配度更高)
- 声明两个独立的容器实例,分别对应两个数据源
// 第一个数据库容器 private static final MariaDBContainer FIRST_DATABASE = new MariaDBContainer<>(DockerImageName.parse(DOCKER_IMAGE).asCompatibleSubstituteFor("mariadb")) .withDatabaseName(FIRST_DB_NAME) .withUsername(DB_USER) .withPassword(DB_PASS); // 第二个数据库容器 private static final MariaDBContainer SECOND_DATABASE = new MariaDBContainer<>(DockerImageName.parse(DOCKER_IMAGE).asCompatibleSubstituteFor("mariadb")) .withDatabaseName(SECOND_DB_NAME) .withUsername(DB_USER) .withPassword(DB_PASS);
- 启动容器并动态覆盖测试环境的数据源配置,配置前缀需和你
application.properties中定义的多数据源名称完全匹配
static { // 启动两个容器 FIRST_DATABASE.start(); SECOND_DATABASE.start(); // 覆盖第一个数据源配置,示例前缀为quarkus.datasource.first,需替换为你实际的数据源名 System.setProperty("quarkus.datasource.first.jdbc.url", FIRST_DATABASE.getJdbcUrl()); System.setProperty("quarkus.datasource.first.username", FIRST_DATABASE.getUsername()); System.setProperty("quarkus.datasource.first.password", FIRST_DATABASE.getPassword()); // 覆盖第二个数据源配置,示例前缀为quarkus.datasource.second,需替换为你实际的数据源名 System.setProperty("quarkus.datasource.second.jdbc.url", SECOND_DATABASE.getJdbcUrl()); System.setProperty("quarkus.datasource.second.username", SECOND_DATABASE.getUsername()); System.setProperty("quarkus.datasource.second.password", SECOND_DATABASE.getPassword()); }
方案二:单容器内创建多数据库(资源占用更低)
如果不想启动两个容器,可通过初始化脚本在同一个MariaDB实例中创建两个数据库:
- 容器配置新增初始化脚本
private static final MariaDBContainer DATABASE = new MariaDBContainer<>(DockerImageName.parse(DOCKER_IMAGE).asCompatibleSubstituteFor("mariadb")) .withDatabaseName(FIRST_DB_NAME) .withUsername(DB_USER) .withPassword(DB_PASS) // 配置初始化SQL脚本,放在test/resources目录下 .withInitScript("init_second_database.sql");
- 编写
init_second_database.sql脚本,创建第二个数据库并授权
CREATE DATABASE IF NOT EXISTS <替换为你的SECOND_DB_NAME>; GRANT ALL PRIVILEGES ON <替换为你的SECOND_DB_NAME>.* TO '<替换为你的DB_USER>'@'%'; FLUSH PRIVILEGES;
- 动态覆盖多数据源配置
static { DATABASE.start(); // 第一个数据源配置 System.setProperty("quarkus.datasource.first.jdbc.url", DATABASE.getJdbcUrl()); System.setProperty("quarkus.datasource.first.username", DATABASE.getUsername()); System.setProperty("quarkus.datasource.first.password", DATABASE.getPassword()); // 第二个数据源配置,替换JDBC URL中的默认库名 String secondJdbcUrl = DATABASE.getJdbcUrl().replace(FIRST_DB_NAME, SECOND_DB_NAME); System.setProperty("quarkus.datasource.second.jdbc.url", secondJdbcUrl); System.setProperty("quarkus.datasource.second.username", DATABASE.getUsername()); System.setProperty("quarkus.datasource.second.password", DATABASE.getPassword()); }
注意事项
如果你的多数据源搭配了多Hibernate持久化单元使用,需保证测试中持久化单元和数据源的关联配置和application.properties中的生产配置完全一致即可。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

