You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot多数据库+Flyway迁移测试:容器与迁移配置问题

解决Spring Boot双数据库(Local+Global)测试配置问题

核心问题分析

你的问题本质是测试环境中未正确将应用的双数据源配置指向Testcontainers启动的两个独立数据库,导致数据源路由错误或数据库定位失败。双容器方案本身是合理的,之前的代码缺失了关键的配置注入环节。

正确配置步骤

1. 完善双Testcontainers容器方案(推荐)

这个方案完全贴合生产环境的独立数据库架构,只需补充将容器连接信息注入Spring配置的逻辑:

完整测试类代码

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MariaDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.flywaydb.core.Flyway;

@Testcontainers
@SpringBootTest
public class DualDbApplicationTest {

    @Container
    public static final MariaDBContainer<?> localDbContainer = new MariaDBContainer<>("mariadb:latest")
            .withDatabaseName("localdb")
            .withUsername("test")
            .withPassword("test");

    @Container
    public static final MariaDBContainer<?> globalDbContainer = new MariaDBContainer<>("mariadb:latest")
            .withDatabaseName("globaldb")
            .withUsername("test")
            .withPassword("test");

    // 动态覆盖Spring配置中的两个数据源
    @DynamicPropertySource
    static void configureDatabases(DynamicPropertyRegistry registry) {
        // Local数据源配置
        registry.add("spring.datasource.local.url", localDbContainer::getJdbcUrl);
        registry.add("spring.datasource.local.username", localDbContainer::getUsername);
        registry.add("spring.datasource.local.password", localDbContainer::getPassword);
        
        // Global数据源配置
        registry.add("spring.datasource.global.url", globalDbContainer::getJdbcUrl);
        registry.add("spring.datasource.global.username", globalDbContainer::getUsername);
        registry.add("spring.datasource.global.password", globalDbContainer::getPassword);
    }

    @BeforeAll
    static void runFlywayMigrations() {
        // 执行Local数据库迁移
        Flyway.configure()
                .dataSource(localDbContainer.getJdbcUrl(), localDbContainer.getUsername(), localDbContainer.getPassword())
                .locations("classpath:db/migration/mariadb")
                .load()
                .migrate();

        // 执行Global数据库迁移(使用测试专用脚本)
        Flyway.configure()
                .dataSource(globalDbContainer.getJdbcUrl(), globalDbContainer.getUsername(), globalDbContainer.getPassword())
                .locations("classpath:db/migration/test")
                .load()
                .migrate();
    }

    // 示例测试用例
    @Test
    void testDualDbOperations() {
        // 编写测试逻辑,比如调用关联双数据源的业务服务
    }
}

2. 匹配应用的双数据源基础配置

确保你的应用已正确配置双数据源,示例application.yml配置:

spring:
  datasource:
    local:
      driver-class-name: org.mariadb.jdbc.Driver
      url: jdbc:mariadb://localhost:3306/localdb
      username: root
      password: root
    global:
      driver-class-name: org.mariadb.jdbc.Driver
      url: jdbc:mariadb://localhost:3306/globaldb
      username: root
      password: root

# 可选:如果需要自动执行Flyway迁移,可添加此配置
flyway:
  local:
    locations: classpath:db/migration/mariadb
    enabled: true
  global:
    locations: classpath:db/migration/test
    enabled: true

3. 常见问题排查

  • 数据库定位失败:检查@DynamicPropertySource中的属性键是否与application.yml里的数据源配置完全一致(比如如果用jdbc-url代替url,需同步修改)。
  • 实体错库:确认实体和Repository已正确关联对应数据源,比如用@Qualifier指定数据源Bean,或在数据源配置类中为不同数据源扫描不同包路径。
  • Flyway迁移未执行:核对locations路径是否正确,测试资源目录下的迁移脚本是否存在(如src/test/resources/db/migration/test)。

为什么不推荐单容器方案?

单容器内创建两个数据库虽技术可行,但会破坏生产环境中双库的隔离性,测试结果参考价值降低,且容易引发数据源路由混乱,因此双容器方案更符合测试场景的真实性。

内容的提问来源于stack exchange,提问作者Adrienn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 23:35:58