使用Flyway Testcontainers测试迁移脚本校验数据时Repository未初始化如何解决
问题根因
你遇到的报错存在两个核心诱因:
- 测试类同时标注
@SpringBootTest和@DataJpaTest导致Spring上下文配置冲突,JPA相关的Repository Bean没有正常初始化,所以teamRepository注入失败,抛出lateinit未初始化异常 - 手动创建的Flyway实例使用独立的Testcontainers数据源,和Spring上下文管理的JPA数据源不统一,哪怕注入成功也会查询到错误的数据库实例
解决方案
- 修正测试类注解冲突
删除重复的测试注解,根据测试场景二选一:
- 若仅需要测试JPA仓库+数据库迁移,保留
@DataJpaTest,新增注解关闭Spring默认的测试内存数据库替换逻辑:
@DataJpaTest @ActiveProfiles("test") @Import(FlywayCallback::class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class DatabaseMigrationScriptIntegrationTest { // 原有类内容 }
- 若需要加载完整的Spring Boot上下文,删除
@DataJpaTest,仅保留@SpringBootTest即可。
- 统一全局数据源配置
不要在测试代码中手动创建Flyway实例,将Testcontainers MySQL的配置写入application-test.properties,让Spring Boot自动管理Flyway、DataSource、JPA的数据源,保证三者使用同一个数据库实例:
# application-test.properties spring.datasource.url=jdbc:tc:mysql://localhost:3306/testdb spring.datasource.username=testing spring.datasource.password=testing spring.flyway.locations=classpath:db/migration,classpath:db/callback spring.flyway.target=10
修改后可以直接注入Spring管理的Flyway实例,不需要自己写创建逻辑。
- 可选方案(保留手动创建Flyway的逻辑)
可以放弃使用Spring注入的Repository,直接用JdbcTemplate连接Flyway使用的数据源做查询校验,无需依赖Spring上下文的Repository注入:
@Test fun runSqlInsertsAfterMigrationAndReadData() { val runAllMigrations = setFlywayConfigurationWithVersion("10") val migrate = runAllMigrations.migrate() // 直接用Flyway的数据源创建JdbcTemplate查询 val jdbcTemplate = JdbcTemplate(runAllMigrations.configuration.dataSource) val email = jdbcTemplate.queryForObject("select email from team where id = ?", String::class.java, "12345") Assertions.assertThat(migrate.migrationsExecuted == 10) assertTrue(email == "someone@someone.com") }
内容的提问来源于stack exchange,提问作者Farukh Khan
相关产品推荐
相关产品推荐

