diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc index 2bfff6c8e93..04693495b8d 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc @@ -84,7 +84,7 @@ The following service connection factories are provided in the `spring-boot-test | Containers of type `PulsarContainer` | `R2dbcConnectionDetails` -| Containers of type `MariaDBContainer`, `MSSQLServerContainer`, `MySQLContainer`, `OracleContainer`, or `PostgreSQLContainer` +| Containers of type `ClickHouseContainer`, `MariaDBContainer`, `MSSQLServerContainer`, `MySQLContainer`, `OracleContainer`, or `PostgreSQLContainer` | `RabbitConnectionDetails` | Containers of type `RabbitMQContainer` diff --git a/spring-boot-project/spring-boot-testcontainers/build.gradle b/spring-boot-project/spring-boot-testcontainers/build.gradle index 80be519f547..d175c0bdf22 100644 --- a/spring-boot-project/spring-boot-testcontainers/build.gradle +++ b/spring-boot-project/spring-boot-testcontainers/build.gradle @@ -64,6 +64,7 @@ dependencies { optional("org.springframework.data:spring-data-neo4j") optional("org.testcontainers:activemq") optional("org.testcontainers:cassandra") + optional("org.testcontainers:clickhouse") optional("org.testcontainers:couchbase") optional("org.testcontainers:elasticsearch") optional("org.testcontainers:grafana") diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/r2dbc/ClickHouseR2dbcContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/r2dbc/ClickHouseR2dbcContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..4e1177e5bca --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/r2dbc/ClickHouseR2dbcContainerConnectionDetailsFactory.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.testcontainers.service.connection.r2dbc; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.testcontainers.clickhouse.ClickHouseContainer; +import org.testcontainers.clickhouse.ClickHouseR2DBCDatabaseContainer; + +import org.springframework.boot.autoconfigure.r2dbc.R2dbcConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link R2dbcConnectionDetails} from + * a {@link ServiceConnection @ServiceConnection}-annotated {@link ClickHouseContainer}. + * + * @author Eddú Meléndez + */ +class ClickHouseR2dbcContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory { + + ClickHouseR2dbcContainerConnectionDetailsFactory() { + super(ANY_CONNECTION_NAME, "io.r2dbc.spi.ConnectionFactoryOptions"); + } + + @Override + public R2dbcConnectionDetails getContainerConnectionDetails(ContainerConnectionSource source) { + return new ClickHouseR2dbcDatabaseContainerConnectionDetails(source); + } + + /** + * {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class ClickHouseR2dbcDatabaseContainerConnectionDetails + extends ContainerConnectionDetails implements R2dbcConnectionDetails { + + private ClickHouseR2dbcDatabaseContainerConnectionDetails( + ContainerConnectionSource source) { + super(source); + } + + @Override + public ConnectionFactoryOptions getConnectionFactoryOptions() { + return ClickHouseR2DBCDatabaseContainer.getOptions(getContainer()); + } + + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories index 14de79b9ea6..902b2c43aca 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories @@ -33,6 +33,7 @@ org.springframework.boot.testcontainers.service.connection.otlp.OpenTelemetryLog org.springframework.boot.testcontainers.service.connection.otlp.OpenTelemetryMetricsContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.otlp.OpenTelemetryTracingContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.pulsar.PulsarContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.r2dbc.ClickHouseR2dbcContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.r2dbc.MariaDbR2dbcContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.r2dbc.MySqlR2dbcContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.r2dbc.OracleFreeR2dbcContainerConnectionDetailsFactory,\ diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/ClickHouseR2dbcContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/ClickHouseR2dbcContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..d5a33c09442 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/ClickHouseR2dbcContainerConnectionDetailsFactoryTests.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.testcontainers.service.connection.r2dbc; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.junit.jupiter.api.Test; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactoryHints; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ClickHouseR2dbcContainerConnectionDetailsFactory}. + * + * @author Eddú Meléndez + */ +class ClickHouseR2dbcContainerConnectionDetailsFactoryTests { + + @Test + void shouldRegisterHints() { + RuntimeHints hints = ContainerConnectionDetailsFactoryHints.getRegisteredHints(getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ConnectionFactoryOptions.class)).accepts(hints); + } + +}