Testcontainersで複数DBに接続

https://start.spring.io/ を使用して適当なプロジェクトを作成する。複数DBとしてmysqlとpostgresqlに接続するのでそれら関連の依存性を追加する。

```gradle:build.gradle
plugins {
	id 'java'
	id 'org.springframework.boot' version '3.3.2'
	id 'io.spring.dependency-management' version '1.1.6'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(17)
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	
	runtimeOnly 'com.mysql:mysql-connector-j'
	runtimeOnly 'org.postgresql:postgresql'
	
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.boot:spring-boot-testcontainers'
	
	testImplementation 'org.testcontainers:junit-jupiter'
	testImplementation 'org.testcontainers:mysql'
	testImplementation 'org.testcontainers:postgresql'
	
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
	useJUnitPlatform()
}
```

テストコードを作成する。

```java
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@SpringBootTest
@Testcontainers
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
class AppTest {

  @Container
  static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:5.7.34");

  @Container
  static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");

  @DynamicPropertySource
  static void registerProperties(DynamicPropertyRegistry registry) {
    registry.add("spring.datasource.mysql.url", () -> mysql.getJdbcUrl());
    registry.add("spring.datasource.mysql.username", () -> mysql.getUsername());
    registry.add("spring.datasource.mysql.password", () -> mysql.getPassword());

    registry.add("spring.datasource.postgres.url", () -> postgres.getJdbcUrl());
    registry.add("spring.datasource.postgres.username", () -> postgres.getUsername());
    registry.add("spring.datasource.postgres.password", () -> postgres.getPassword());
  }

  @TestConfiguration
  static class TestConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.mysql")
    public DataSourceProperties mysqlDataSourceProperties() {
      return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.postgres")
    public DataSourceProperties postgresDataSourceProperties() {
      return new DataSourceProperties();
    }

    @Bean
    public DataSource mysqlDataSource() {
      return mysqlDataSourceProperties()
          .initializeDataSourceBuilder()
          .build();
    }

    @Bean
    public DataSource postgresDataSource() {
      return postgresDataSourceProperties()
          .initializeDataSourceBuilder()
          .build();
    }
  }

  @Test
  void test(
      @Qualifier("mysqlDataSource") DataSource mysqlDataSource,
      @Qualifier("postgresDataSource") DataSource postgresDataSource) {
    Integer v1 = JdbcClient.create(mysqlDataSource).sql("select cast('1' AS unsigned)")
        .query(Integer.class).single();
    System.out.println("mysql:" + v1);
    Integer v2 = JdbcClient.create(postgresDataSource).sql("select cast('1' AS int)")
        .query(Integer.class).single();
    System.out.println("postgres:" + v2);
  }
}

```

スマートなやり方が分からなかったので、```@DynamicPropertySource```で動的にデータソース関連プロパティを単純に書き換えている。```@ServiceConnection```が使用できそうな気もするけど、auto-configを見ると単一DBにしか対応してないのかな……という感じもしたが良く分からない。springの```ConnectionDetails```の仕組みを利用しているので、これをもう少し調べれば何とかなるかな……という気もする。これ以上は調べきれなかったので一旦これで投稿してしまう。