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

如何强制Flyway每次新增数据库迁移都配套对应版本测试数据脚本?

Flyway 主迁移脚本强制匹配测试数据脚本实现方案

核心思路

通过读取所有主迁移脚本和测试数据脚本的版本号,校验每一个主迁移版本都存在对应的[主版本号].1格式的测试数据版本,不存在则测试断言失败。
推荐直接使用Flyway自带的API读取迁移脚本信息,避免自行解析文件可能出现的规则适配错误。

具体代码实现

直接在原有的集成测试类中新增版本校验的测试方法即可,修改后的完整测试类如下:

@SpringBootTest
@ActiveProfiles("test")
@Import(FlywayCallback::class)
class DatabaseMigrationScriptIntegrationTest {

  @Autowired
  private lateinit var strategy: FlywayMigrationConfig

  private val log = LogFactory.getLog(javaClass)
  
  // 可选:不需要配套测试数据的主版本白名单,按需添加
  private val ignoredMainVersions = setOf<String>()

  @BeforeEach
  fun setUp() {
    strategy.cleanMigrateStrategy()
  }
  
  @Test
  fun `所有主迁移脚本都存在对应的测试数据脚本`() {
    val flyway = flywaySetup()
    // 获取所有识别到的迁移脚本
    val allMigrations = flyway.info().all()
    
    // 区分主迁移脚本和测试数据脚本
    val mainMigrationVersions = mutableSetOf<String>()
    val testDataMigrationVersions = mutableSetOf<String>()
    
    allMigrations.forEach { migration ->
      val scriptPath = migration.script
      if (scriptPath.startsWith("db/migration/afterEachMigrate")) {
        testDataMigrationVersions.add(migration.version.version)
      } else if (scriptPath.startsWith("db/migration")) {
        val mainVersion = migration.version.version
        if (!ignoredMainVersions.contains(mainVersion)) {
          mainMigrationVersions.add(mainVersion)
        }
      }
    }
    
    // 校验每个主版本都有对应的 x.1 测试数据版本
    val missingTestVersions = mainMigrationVersions.filter { mainVer ->
      val expectedTestVer = "$mainVer.1"
      !testDataMigrationVersions.contains(expectedTestVer)
    }
    
    Assertions.assertThat(missingTestVersions)
      .withFailMessage("以下主迁移版本缺少对应的测试数据脚本:${missingTestVersions.joinToString(", ")}")
      .isEmpty()
  }

  @Test
  fun successfullyRunsMigrationsWithTestingData() {
    val configureFlyway = flywaySetup()
    val runMigrations = configureFlyway.migrate()
    Assertions.assertThat(runMigrations.migrationsExecuted).isGreaterThan(0)
  }

  private fun flywaySetup(): Flyway {
    return Flyway.configure()
      .dataSource("jdbc:tc:mysql://localhost:3306", "test", "test")
      .locations("classpath:db/migration", "classpath:db/migration/afterEachMigrate")
      .callbacks(FlywayCallback())
      .load()
  }
}

补充说明

  • 代码中预留了ignoredMainVersions白名单,如果你有部分特殊的主迁移脚本不需要配套测试数据,可以直接把版本号加入该集合跳过校验。
  • 如果你不想依赖Flyway API做版本读取,也可以使用PathMatchingResourcePatternResolver自行扫描两个目录下的SQL文件,通过正则匹配提取版本号做校验,逻辑完全一致。
  • 校验测试会在迁移执行测试之前运行,只要存在未配套测试数据的主迁移脚本,测试会直接失败,阻断后续流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 19:06:07