如何用Testcontainers实现多数据库集成测试并创建指定Catalog表
问题解决方法
问题原因
Hibernate的ddl-auto=create模式不会自动创建指定的catalog(MariaDB中catalog与database等价),只会在已存在的catalog下生成表。而Testcontainers启动的MariaDB容器默认仅包含你指定的test数据库,GE_events catalog不存在,导致Event表无法创建。
解决方案
方案一:通过Testcontainers初始化脚本提前创建catalog
放弃jdbc:tc:的简化URL配置,手动定义MariaDB容器并指定初始化脚本,在脚本中创建GE_events catalog:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {"spring.jpa.hibernate.ddl-auto=create", "spring.jpa.show_sql=true", "javax.persistence.sql-load-script-source=data.sql"}) @RunWith(SpringRunner.class) public class ServiceIntTest { // 定义MariaDB容器并指定初始化脚本 @Container public static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:latest") .withInitScript("init-catalog.sql"); // 动态注入数据源属性 @DynamicPropertySource static void setDatasourceProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", mariaDBContainer::getJdbcUrl); registry.add("spring.datasource.username", mariaDBContainer::getUsername); registry.add("spring.datasource.password", mariaDBContainer::getPassword); registry.add("spring.datasource.driver-class-name", () -> "org.testcontainers.jdbc.ContainerDatabaseDriver"); } }
在项目resources目录下创建init-catalog.sql文件,内容如下:
CREATE DATABASE IF NOT EXISTS GE_events;
方案二:通过JDBC URL参数指定初始化脚本
保持原有测试类结构,在JDBC URL中添加TC_INITSCRIPT参数指定初始化脚本:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {"spring.jpa.hibernate.ddl-auto=create", "spring.jpa.show_sql=true", "javax.persistence.sql-load-script-source=data.sql", "spring.datasource.url= jdbc:tc:mariadb://localhost/test?TC_INITSCRIPT=classpath:init-catalog.sql", "spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver"}) @RunWith(SpringRunner.class) public class ServiceIntTest { ... }
同样在resources下创建init-catalog.sql文件,内容为创建GE_events的SQL语句。
方案三:使用@Sql注解在测试前执行创建语句
无需额外脚本,直接在测试类上添加@Sql注解,在Hibernate执行DDL前创建catalog:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {"spring.jpa.hibernate.ddl-auto=create", "spring.jpa.show_sql=true", "javax.persistence.sql-load-script-source=data.sql", "spring.datasource.url= jdbc:tc:mariadb://localhost/test", "spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver"}) @RunWith(SpringRunner.class) @Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, statements = "CREATE DATABASE IF NOT EXISTS GE_events;") public class ServiceIntTest { ... }
验证逻辑
上述方案都会在Testcontainers启动MariaDB容器后、Hibernate执行表生成逻辑前创建GE_events catalog。之后Hibernate会自动在GE_events下创建event表,同时在默认的test数据库下创建user表,满足测试需求。
内容的提问来源于stack exchange,提问作者lrkwz
相关产品推荐
相关产品推荐

