diff --git a/pom.xml b/pom.xml
index 665d56cc..e00e6b70 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-r2dbc
- 1.0.0.BUILD-SNAPSHOT
+ 1.0.0.gh-29-SNAPSHOT
Spring Data R2DBC
Spring Data module for R2DBC.
diff --git a/src/test/java/org/springframework/data/r2dbc/testing/ExternalDatabase.java b/src/test/java/org/springframework/data/r2dbc/testing/ExternalDatabase.java
index 6a1832ae..a538f630 100644
--- a/src/test/java/org/springframework/data/r2dbc/testing/ExternalDatabase.java
+++ b/src/test/java/org/springframework/data/r2dbc/testing/ExternalDatabase.java
@@ -24,6 +24,8 @@
import org.junit.AssumptionViolatedException;
import org.junit.rules.ExternalResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* {@link ExternalResource} wrapper to encapsulate {@link ProvidedDatabase} and
@@ -33,6 +35,8 @@
*/
public abstract class ExternalDatabase extends ExternalResource {
+ private static Logger LOG = LoggerFactory.getLogger(ExternalDatabase.class);
+
/**
* @return the post of the database service.
*/
@@ -53,16 +57,35 @@ public abstract class ExternalDatabase extends ExternalResource {
*/
public abstract String getUsername();
+ /**
+ * Throws an {@link AssumptionViolatedException} if the database cannot be reached.
+ */
@Override
protected void before() {
+ if (!checkValidity()) {
+ throw new AssumptionViolatedException(
+ String.format("Cannot connect to %s:%d. Skipping tests.", getHostname(), getPort()));
+ }
+ }
+
+ /**
+ * performs a test if the database can actually be reached.
+ *
+ * @return true, if the database could be reached.
+ */
+ boolean checkValidity() {
+
try (Socket socket = new Socket()) {
+
socket.connect(new InetSocketAddress(getHostname(), getPort()), Math.toIntExact(TimeUnit.SECONDS.toMillis(5)));
+ return true;
} catch (IOException e) {
- throw new AssumptionViolatedException(
- String.format("Cannot connect to %s:%d. Skipping tests.", getHostname(), getPort()));
+ LOG.debug("external database not available.", e);
}
+
+ return false;
}
/**
@@ -122,4 +145,42 @@ public String getPassword() {
return password;
}
}
+
+ /**
+ * An {@link ExternalDatabase} that couldn't get constructed.
+ *
+ * @author Jens Schauder
+ */
+ static class NoSuchDatabase extends ExternalDatabase {
+
+ @Override
+ boolean checkValidity() {
+ return false;
+ }
+
+ @Override
+ public int getPort() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getHostname() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getDatabase() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getUsername() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getPassword() {
+ throw new UnsupportedOperationException();
+ }
+ }
}
diff --git a/src/test/java/org/springframework/data/r2dbc/testing/PostgresTestSupport.java b/src/test/java/org/springframework/data/r2dbc/testing/PostgresTestSupport.java
index d7608f09..74159cb8 100644
--- a/src/test/java/org/springframework/data/r2dbc/testing/PostgresTestSupport.java
+++ b/src/test/java/org/springframework/data/r2dbc/testing/PostgresTestSupport.java
@@ -4,18 +4,24 @@
import io.r2dbc.postgresql.PostgresqlConnectionFactory;
import io.r2dbc.spi.ConnectionFactory;
+import java.util.function.Supplier;
+
import javax.sql.DataSource;
import org.postgresql.ds.PGSimpleDataSource;
import org.springframework.data.r2dbc.testing.ExternalDatabase.ProvidedDatabase;
+import org.testcontainers.containers.PostgreSQLContainer;
/**
* Utility class for testing against Postgres.
*
* @author Mark Paluch
+ * @author Jens Schauder
*/
public class PostgresTestSupport {
+ private static ExternalDatabase testContainerDatabase;
+
public static String CREATE_TABLE_LEGOSET = "CREATE TABLE legoset (\n" //
+ " id integer CONSTRAINT id PRIMARY KEY,\n" //
+ " name varchar(255) NOT NULL,\n" //
@@ -31,30 +37,91 @@ public class PostgresTestSupport {
public static String INSERT_INTO_LEGOSET = "INSERT INTO legoset (id, name, manual) VALUES($1, $2, $3)";
/**
- * Returns a locally provided database at {@code postgres:@localhost:5432/postgres}.
+ * Returns a database either hosted locally at {@code postgres:@localhost:5432/postgres} or running inside Docker.
*
- * @return
+ * @return information about the database. Guaranteed to be not {@literal null}.
*/
public static ExternalDatabase database() {
- return local();
+
+ if (Boolean.getBoolean("spring.data.r2dbc.test.preferLocalDatabase")) {
+
+ return getFirstWorkingDatabase( //
+ PostgresTestSupport::local, //
+ PostgresTestSupport::testContainer //
+ );
+ } else {
+
+ return getFirstWorkingDatabase( //
+ PostgresTestSupport::testContainer, //
+ PostgresTestSupport::local //
+ );
+ }
+ }
+
+ private static ExternalDatabase getFirstWorkingDatabase(Supplier first,
+ Supplier second) {
+
+ ExternalDatabase database = first.get();
+ if (database.checkValidity()) {
+ return database;
+ } else {
+ return second.get();
+ }
}
/**
* Returns a locally provided database at {@code postgres:@localhost:5432/postgres}.
- *
- * @return
*/
private static ExternalDatabase local() {
- return ProvidedDatabase.builder().hostname("localhost").port(5432).database("postgres").username("postgres")
+
+ return ProvidedDatabase.builder() //
+ .hostname("localhost") //
+ .port(5432) //
+ .database("postgres") //
+ .username("postgres") //
.password("").build();
}
+ /**
+ * Returns a database provided via Testcontainers.
+ */
+ private static ExternalDatabase testContainer() {
+
+ if (testContainerDatabase == null) {
+
+ try {
+ PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer();
+ postgreSQLContainer.start();
+
+ testContainerDatabase = ProvidedDatabase.builder() //
+ .hostname("localhost") //
+ .port(postgreSQLContainer.getFirstMappedPort()) //
+ .database(postgreSQLContainer.getDatabaseName()) //
+ .username(postgreSQLContainer.getUsername()) //
+ .password(postgreSQLContainer.getPassword()).build();
+
+ } catch (IllegalStateException ise) {
+ // docker is not available.
+ testContainerDatabase = new ExternalDatabase.NoSuchDatabase();
+ }
+
+ }
+
+ return testContainerDatabase;
+ }
+
/**
* Creates a new {@link ConnectionFactory} configured from the {@link ExternalDatabase}..
*/
public static ConnectionFactory createConnectionFactory(ExternalDatabase database) {
- return new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder().host(database.getHostname())
- .database(database.getDatabase()).username(database.getUsername()).password(database.getPassword()).build());
+
+ return new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder() //
+ .host(database.getHostname()) //
+ .database(database.getDatabase()) //
+ .port(database.getPort()) //
+ .username(database.getUsername()) //
+ .password(database.getPassword()) //
+ .build());
}
/**
@@ -72,4 +139,5 @@ public static DataSource createDataSource(ExternalDatabase database) {
return dataSource;
}
+
}
diff --git a/src/test/java/org/springframework/data/r2dbc/testing/SqlServerTestSupport.java b/src/test/java/org/springframework/data/r2dbc/testing/SqlServerTestSupport.java
index 3fb08ad7..d52c8476 100644
--- a/src/test/java/org/springframework/data/r2dbc/testing/SqlServerTestSupport.java
+++ b/src/test/java/org/springframework/data/r2dbc/testing/SqlServerTestSupport.java
@@ -33,31 +33,35 @@ public class SqlServerTestSupport {
/**
* Returns a locally provided database at {@code sqlserver:@localhost:1433/master}.
- *
- * @return
*/
public static ExternalDatabase database() {
return local();
}
/**
- * Returns a locally provided database at {@code postgres:@localhost:5432/postgres}.
- *
- * @return
+ * Returns a locally provided database at {@code sqlserver:@localhost:1433/master}.
*/
private static ExternalDatabase local() {
- return ProvidedDatabase.builder().hostname("localhost").port(1433).database("master").username("sa")
- .password("A_Str0ng_Required_Password").build();
+
+ return ProvidedDatabase.builder() //
+ .hostname("localhost") //
+ .port(1433) //
+ .database("master") //
+ .username("sa") //
+ .password("A_Str0ng_Required_Password") //
+ .build();
}
/**
* Creates a new {@link ConnectionFactory} configured from the {@link ExternalDatabase}..
*/
public static ConnectionFactory createConnectionFactory(ExternalDatabase database) {
+
return new MssqlConnectionFactory(MssqlConnectionConfiguration.builder().host(database.getHostname()) //
.database(database.getDatabase()) //
.username(database.getUsername()) //
.password(database.getPassword()) //
+ .port(database.getPort()) //
.build());
}