Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Testcontainers parallel tests: one database can leak another test's rows

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

Sharing a database container across test classes saves startup time but requires data and transaction isolation between concurrent tests.

A shared port is not a private database

Two test classes can reuse the same Spring context and PostgreSQL container. If both insert order 47 and one truncates a table in @BeforeEach, the result depends on scheduling. A rollback annotation on the test method does not clean work done by a worker thread or a separate transaction. Thread-bound transactions and new transactions make that leak easy to miss.

Pick one isolation mechanism

Use unique tenant and command IDs per test when assertions can filter by them. For tests that verify global counts or migration state, use a separate database, schema, or serialized suite; do not rely on a random sleep. Keep cleanup tied to the fixture it created and never truncate shared tables while parallel tests run. Migrations should be applied once by the chosen context owner, not raced by every test class.

Run the hostile schedule

Start both classes in parallel. Pause one test after insert, let the other complete its cleanup, then release the first and assert its row remains. Repeat with a worker that commits outside the test transaction. The code documents unique IDs; CI must still run the actual parallel schedule for this guarantee.

Implementation sketch

Java
String tenantId = "test-" + UUID.randomUUID();
ledger.insert(tenantId, "order-47", 23);
assertEquals(23, ledger.totalForTenant(tenantId));
// Cleanup only rows owned by tenantId.

Cost and verification

Unique test data is cheap but can grow a long-lived container's tables. Separate schemas or containers cost startup time and memory but give stronger isolation for global-state tests.

Common Mistakes

  • Do not truncate a shared database from a parallel test's setup or cleanup.
  • Do not assume test rollback covers @Async work or REQUIRES_NEW scopes.
  • Do not claim parallel safety from a sequential local run.

Read next

Spring Boot Testcontainers: service connections and cached-context lifecycle, Spring Boot Testcontainers and Flyway: let one owner prepare the test schema, Spring imperative transaction: a worker thread does not inherit it, Spring REQUIRES_NEW: budget the second database connection.

spring
spring-boot
testing
testcontainers-parallel-isolation
Storage details