diff --git a/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java b/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java index cf6c995528f..5e9fd1f01c7 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java +++ b/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java @@ -76,6 +76,26 @@ public JdbcDatabaseContainer(final DockerImageName dockerImageName) { */ public abstract String getJdbcUrl(); + /** + * Returns an R2DBC URL that may be used to connect to the dockerized DB using reactive drivers. + *

+ * The default implementation converts the JDBC URL to R2DBC format by replacing + * the "jdbc:" prefix with "r2dbc:". Subclasses may override this method if + * a different conversion is required. + * + * @return an R2DBC URL for reactive database connections + * @see R2DBC Specification + */ + public String getR2dbcUrl() { + String jdbcUrl = getJdbcUrl(); + if (jdbcUrl != null && jdbcUrl.startsWith("jdbc:")) { + return "r2dbc:" + jdbcUrl.substring(5); + } + throw new UnsupportedOperationException( + "Cannot convert JDBC URL to R2DBC format. Override getR2dbcUrl() in subclass." + ); + } + /** * @return the database name */ diff --git a/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java b/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java index ca41c3f5d1c..40002c2061c 100644 --- a/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java +++ b/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java @@ -7,11 +7,33 @@ import java.sql.Connection; import java.sql.SQLException; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.Mockito.mock; class JdbcDatabaseContainerTest { + @Test + void getR2dbcUrlConvertsJdbcUrlToR2dbcFormat() { + JdbcDatabaseContainer container = new JdbcDatabaseContainerStubWithUrl( + "mysql:latest", + "jdbc:mysql://localhost:3306/testdb" + ); + + String r2dbcUrl = container.getR2dbcUrl(); + + assertThat(r2dbcUrl).isEqualTo("r2dbc:mysql://localhost:3306/testdb"); + } + + @Test + void getR2dbcUrlThrowsExceptionWhenJdbcUrlIsNull() { + JdbcDatabaseContainer container = new JdbcDatabaseContainerStub("mysql:latest"); + + assertThatExceptionOfType(UnsupportedOperationException.class) + .isThrownBy(container::getR2dbcUrl) + .withMessageContaining("Cannot convert JDBC URL to R2DBC format"); + } + @Test void anExceptionIsThrownIfJdbcIsNotAvailable() { JdbcDatabaseContainer jdbcContainer = new JdbcDatabaseContainerStub("mysql:latest") @@ -69,4 +91,19 @@ protected Logger logger() { @Override public void setDockerImageName(@NonNull String dockerImageName) {} } + + static class JdbcDatabaseContainerStubWithUrl extends JdbcDatabaseContainerStub { + + private final String jdbcUrl; + + public JdbcDatabaseContainerStubWithUrl(@NonNull String dockerImageName, String jdbcUrl) { + super(dockerImageName); + this.jdbcUrl = jdbcUrl; + } + + @Override + public String getJdbcUrl() { + return jdbcUrl; + } + } }