在SpringBoot项目里配置Flyway并借助TestContainer写集成测试

配置flyway

  • 配置application.yml文件
    可以在Spring Boot Reference Documentation的Application Properties中找到关于application.yml的各种配置
    • 配置数据源
      spring:
        profiles:
          active: ${SPRING_PROFILE}
        datasource:
          url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
          username: ${DB_USER}
          password: ${DB_USER_PASSWORD}
          driver-class-name: org.postgresql.Driver
      
    • 开启详细日志打印(在定位问题时很有用):
      logging:
        level:
          root: debug
      
  • build.gradle里添加依赖
    implementation 'org.flywaydb:flyway-core:8.0.1'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc:2.5.6'
	runtimeOnly 'org.postgresql:postgresql:42.3.0'

spring-boot-starter-jdbc可用于确保datasource可连接。

集成测试

当在项目中配置了数据库,又打算写集成测试时,有两种方案可以选择:

方案1

借助h2数据库搭建测试数据库

  • build.gradle文件中添加依赖:testImplementation ‘com.h2database:h2:1.4.200’
  • application-test.yml中添加配置:
spring:
  datasource:
    url: jdbc:h2:~/test
    username: lead_store_user
    password: lead_store
  • 编写继承测试
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
class BooleanTest {
@Test
public void isTure {
assertThat(true, is(true));
}
}
  • 在配置了flyway的情况下,若执行flyway管理的sql报错之后,修复sql正确后,可以在测试中加上如下Bean
@Configuration
public class TestConfiguration {
  @Bean
  @Profile("test")
  public FlywayMigrationStrategy cleanMigrateStrategy() {
    return Flyway::repair;
  }
}

方案2

借助TestContainer搭建测试数据库
参考文档:spring-boot-testcontainers-integration-test

  • build.gradle文件中添加依赖:
    testImplementation 'org.testcontainers:postgresql:1.16.2'
    testImplementation 'org.testcontainers:testcontainers:1.15.3'
  • 编写继承测试的Base类,并由其他集成测试类继承
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(initializers = {IntegrationTestBase.DatabaseConnectionInjector.class})
public class IntegrationTestBase {
  private static final PostgreSQLContainer POSTGRE_SQL_CONTAINER =
      new PostgreSQLContainer("postgres:12.8")
          .withDatabaseName("db_name")
          .withUsername("user_name")
          .withPassword("password");

  static {
    POSTGRE_SQL_CONTAINER.start();
  }

  static class DatabaseConnectionInjector
      implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
      TestPropertyValues.of(
              "spring.datasource.url=" + POSTGRE_SQL_CONTAINER.getJdbcUrl(),
              "spring.datasource.username=" + POSTGRE_SQL_CONTAINER.getUsername(),
              "spring.datasource.password=" + POSTGRE_SQL_CONTAINER.getPassword())
          .applyTo(applicationContext.getEnvironment());
    }
  }
}

在docker中运行测试时,如果出现如下报错java.lang.IllegalStateException: Could not find a valid Docker environment. Please see logs and check configuration可以在TestContainer仓库的Issue中找到解决方案, 需要在测试容器中添加如下卷:

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

挂载的/var/run/docker.sock文件是Docker守护进程(Docker daemon)默认监听的Unix域套接字(Unix domain socket),容器中的进程可以通过它与Docker守护进程进行通信。

上一篇:SpringBoot 配置多数据源并动态切换


下一篇:VSCode1.59版本发布