From 0c22448747237bbb6fb896afacc016f0f78f22f5 Mon Sep 17 00:00:00 2001 From: Mayur Saikia Date: Sun, 12 Oct 2025 12:06:41 +0530 Subject: [PATCH] Testcontainers Java sample: fix test assertions and wait loop, modernize JDBC/JUnit, and clean up POM --- .../LocalStackTestcontainers/pom.xml | 19 +++------- .../src/main/java/RDS.java | 35 +++++++++---------- .../src/test/java/TestRDS.java | 24 +++++++++---- testcontainers-java-sample/README.md | 22 ++++++++---- 4 files changed, 54 insertions(+), 46 deletions(-) diff --git a/testcontainers-java-sample/LocalStackTestcontainers/pom.xml b/testcontainers-java-sample/LocalStackTestcontainers/pom.xml index 5cec93d..6fec2c7 100644 --- a/testcontainers-java-sample/LocalStackTestcontainers/pom.xml +++ b/testcontainers-java-sample/LocalStackTestcontainers/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk bom - 2.17.224 + 2.25.62 pom import @@ -27,7 +27,7 @@ junit junit - 4.12 + 4.13.2 test @@ -38,10 +38,6 @@ software.amazon.awssdk rds - - software.amazon.awssdk - s3 - software.amazon.awssdk cognitoidentity @@ -53,20 +49,13 @@ org.testcontainers localstack - 1.19.2 - test - - - - com.amazonaws - aws-java-sdk-s3 - 1.11.914 + 1.20.2 test org.postgresql postgresql - 9.3-1100-jdbc4 + 42.7.4 diff --git a/testcontainers-java-sample/LocalStackTestcontainers/src/main/java/RDS.java b/testcontainers-java-sample/LocalStackTestcontainers/src/main/java/RDS.java index dd436b7..26742a1 100644 --- a/testcontainers-java-sample/LocalStackTestcontainers/src/main/java/RDS.java +++ b/testcontainers-java-sample/LocalStackTestcontainers/src/main/java/RDS.java @@ -24,28 +24,27 @@ protected static String test_connection(String hostname, Integer port, String db String url = String.format("jdbc:postgresql://%s:%d/%s", hostname, port, dbname); c = DriverManager.getConnection(url, DEFAULT_USER, DEFAULT_PW); c.setAutoCommit(true); - Statement stmt = c.createStatement(); - String sql = "CREATE TABLE HELLO " + - "(ID INT PRIMARY KEY NOT NULL," + - " NAME TEXT NOT NULL) "; - stmt.executeUpdate(sql); + try (Statement stmt = c.createStatement()) { + String sql = "CREATE TABLE HELLO " + + "(ID INT PRIMARY KEY NOT NULL," + + " NAME TEXT NOT NULL) "; + stmt.executeUpdate(sql); - sql = "INSERT INTO HELLO (ID,NAME) " - + "VALUES (1, 'world');"; - stmt.executeUpdate(sql); - ResultSet rs = stmt.executeQuery( "SELECT * FROM HELLO;" ); - String response = ""; - while( rs.next()) { - int id = rs.getInt("id"); - String name = rs.getString("name"); - response += String.format("ID = %d\nNAME = %s", id, name); + sql = "INSERT INTO HELLO (ID,NAME) VALUES (1, 'world');"; + stmt.executeUpdate(sql); + String response = ""; + try (ResultSet rs = stmt.executeQuery("SELECT * FROM HELLO;")) { + while (rs.next()) { + int id = rs.getInt("id"); + String name = rs.getString("name"); + response += String.format("ID = %d\nNAME = %s", id, name); + } + } + return response; } - rs.close(); - stmt.close(); - return response; } finally { try { - c.close(); + if (c != null) c.close(); } catch (SQLException e) { // we can ignore error here } diff --git a/testcontainers-java-sample/LocalStackTestcontainers/src/test/java/TestRDS.java b/testcontainers-java-sample/LocalStackTestcontainers/src/test/java/TestRDS.java index 5d28fc0..175e07c 100644 --- a/testcontainers-java-sample/LocalStackTestcontainers/src/test/java/TestRDS.java +++ b/testcontainers-java-sample/LocalStackTestcontainers/src/test/java/TestRDS.java @@ -30,9 +30,9 @@ public class TestRDS { */ @Rule public LocalStackContainer localstack = new LocalStackContainer(localstackImage) - .withExposedPorts(4510, 4511, 4512, 4513, 4514) // TODO the port can have any value between 4510-4559, but LS starts from 4510 - .withEnv("LOCALSTACK_AUTH_TOKEN", api_key) // TODO add your Auth Token here - .withServices(LocalStackContainer.EnabledService.named("rds")); + .withExposedPorts(4510, 4511, 4512, 4513, 4514) // TODO the port can have any value between 4510-4559, but LS starts from 4510 + .withEnv("LOCALSTACK_AUTH_TOKEN", api_key) // TODO add your Auth Token here + .withServices(LocalStackContainer.EnabledService.named("rds")); @Test @@ -51,8 +51,19 @@ public void testRds() throws UnknownHostException, URISyntaxException { DescribeDbInstancesRequest request = DescribeDbInstancesRequest.builder().dbInstanceIdentifier(identifier).build(); DescribeDbInstancesResponse describedb = rds.describeDBInstances(request); - // wait for db to be ready - while(! describedb.dbInstances().get(0).dbInstanceStatus().equalsIgnoreCase("available")) { + // wait for db to be ready with a small backoff and a timeout to avoid busy-waiting + long start = System.currentTimeMillis(); + long timeoutMs = 30_000; // 30s + while (!describedb.dbInstances().get(0).dbInstanceStatus().equalsIgnoreCase("available")) { + if (System.currentTimeMillis() - start > timeoutMs) { + fail("Timed out waiting for RDS instance to become available"); + } + try { + Thread.sleep(200); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + fail("Interrupted while waiting for RDS instance to become available"); + } describedb = rds.describeDBInstances(request); } @@ -65,7 +76,8 @@ public void testRds() throws UnknownHostException, URISyntaxException { // try to connect to database in our example we simply insert some dummy data String actual = RDS.test_connection(localstack.getHost(), mapped_port, "hello"); String expected = "ID = 1\nNAME = world"; - assertEquals(actual, expected); + // JUnit expects (expected, actual) + assertEquals(expected, actual); } catch (Exception e) { fail("testing connection with database failed"); } diff --git a/testcontainers-java-sample/README.md b/testcontainers-java-sample/README.md index 7b5ac14..5786bf7 100644 --- a/testcontainers-java-sample/README.md +++ b/testcontainers-java-sample/README.md @@ -1,14 +1,22 @@ # Example using RDS with Localstack Testcontainers -Testcontainers need a special setup to use services like RDS, which may use any port to expose the database. -The sample explains how the mapping works, and how you need to configure Testcontainers in order to connect to the RDS instance from your test. +Testcontainers need a special setup to use services like RDS, which may use any port to expose the database. The sample explains how the mapping works, and how you need to configure Testcontainers in order to connect to the RDS instance from your test. + +## Prerequisites +- Docker running +- JDK 11+ +- Maven 3.8+ +- LocalStack Pro Auth Token in `LOCALSTACK_AUTH_TOKEN` ## Run Example -* Import the project (e.g. in IntelliJ), -* configure your LOCALSTACK_AUTH_TOKEN as environment variable, -* and then run the test `TestRDS`. +You can run the JUnit test either in your IDE or from the command line: + +``` +cd testcontainers-java-sample/LocalStackTestcontainers +export LOCALSTACK_AUTH_TOKEN=... # required for RDS (Pro feature) +mvn -q -Dtest=TestRDS test +``` -It will create a LocalStack Testcontainer and a postgres database instance using RDSClient. -The database will then be filled with some data, and queried afterwards. +This will start a LocalStack Testcontainers instance, create a Postgres database via the RDS client, insert a row, and query it.