diff --git a/modules/jdbc/build.gradle b/modules/jdbc/build.gradle index 8b509f54fdb..8f2d8954985 100644 --- a/modules/jdbc/build.gradle +++ b/modules/jdbc/build.gradle @@ -11,4 +11,5 @@ dependencies { testCompile 'com.zaxxer:HikariCP-java6:2.3.13' testCompile 'com.googlecode.junit-toolbox:junit-toolbox:2.4' testCompile 'org.rnorth.visible-assertions:visible-assertions:2.1.2' + testCompile 'org.assertj:assertj-core:3.16.1' } 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 26d699a1813..cf5ae150575 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java +++ b/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java @@ -1,7 +1,9 @@ package org.testcontainers.containers; import com.github.dockerjava.api.command.InspectContainerResponse; +import java.sql.Statement; import lombok.NonNull; +import lombok.SneakyThrows; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import org.testcontainers.containers.traits.LinkableContainer; @@ -130,25 +132,23 @@ public SELF withInitScript(String initScriptPath) { return self(); } + @SneakyThrows(InterruptedException.class) @Override protected void waitUntilContainerStarted() { logger().info("Waiting for database connection to become available at {} using query '{}'", getJdbcUrl(), getTestQueryString()); // Repeatedly try and open a connection to the DB and execute a test query long start = System.currentTimeMillis(); - try { - while (System.currentTimeMillis() < start + (1000 * startupTimeoutSeconds)) { - try { - if (!isRunning()) { - Thread.sleep(100L); - continue; // Don't attempt to connect yet - } - try (Connection connection = createConnection("")) { - boolean testQuerySucceeded = connection.createStatement().execute(this.getTestQueryString()); - if (testQuerySucceeded) { - break; - } + while (System.currentTimeMillis() < start + (1000 * startupTimeoutSeconds)) { + if (!isRunning()) { + Thread.sleep(100L); + } else { + try (Statement statement = createConnection("").createStatement()) { + boolean testQuerySucceeded = statement.execute(this.getTestQueryString()); + if (testQuerySucceeded) { + logger().info("Container is started (JDBC URL: {})", this.getJdbcUrl()); + return; } } catch (NoDriverFoundException e) { // we explicitly want this exception to fail fast without retries @@ -159,12 +159,12 @@ protected void waitUntilContainerStarted() { Thread.sleep(100L); } } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ContainerLaunchException("Container startup wait was interrupted", e); } - logger().info("Container is started (JDBC URL: {})", JdbcDatabaseContainer.this.getJdbcUrl()); + throw new IllegalStateException( + String.format("Container is started, but cannot be accessed by (JDBC URL: %s), please check container logs", + this.getJdbcUrl()) + ); } @Override diff --git a/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java b/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java new file mode 100644 index 00000000000..9f0cf514558 --- /dev/null +++ b/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java @@ -0,0 +1,71 @@ +package org.testcontainers.containers; + +import java.sql.Connection; +import java.sql.SQLException; +import lombok.NonNull; +import org.junit.Test; +import org.slf4j.Logger; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.mock; + +public class JdbcDatabaseContainerTest { + + @Test + public void anExceptionIsThrownIfJdbcIsNotAvailable() { + JdbcDatabaseContainer jdbcContainer = new JdbcDatabaseContainerStub("mysql:latest") + .withStartupTimeoutSeconds(1); + + assertThatExceptionOfType(IllegalStateException.class).isThrownBy(jdbcContainer::waitUntilContainerStarted); + } + + static class JdbcDatabaseContainerStub extends JdbcDatabaseContainer { + + public JdbcDatabaseContainerStub(@NonNull String dockerImageName) { + super(dockerImageName); + } + + @Override + public String getDriverClassName() { + return null; + } + + @Override + public String getJdbcUrl() { + return null; + } + + @Override + public String getUsername() { + return null; + } + + @Override + public String getPassword() { + return null; + } + + @Override + protected String getTestQueryString() { + return null; + } + + @Override + public boolean isRunning() { + return true; + } + + @Override + public Connection createConnection(String queryString) throws SQLException, NoDriverFoundException { + throw new SQLException("Could not create new connection"); + } + + @Override + protected Logger logger() { + return mock(Logger.class); + } + + @Override + public void setDockerImageName(@NonNull String dockerImageName) {} + } +}