or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/maven-org-testcontainers--junit-jupiter

JUnit Jupiter extension that enables automatic lifecycle management of Docker containers in JUnit 5 tests

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/org.testcontainers/junit-jupiter@1.21.x

To install, run

npx @tessl/cli install tessl/maven-org-testcontainers--junit-jupiter@1.21.0

index.mddocs/

Testcontainers JUnit Jupiter

A JUnit Jupiter extension that enables automatic lifecycle management of Docker containers in JUnit 5 tests. The extension provides annotations to seamlessly integrate container-based testing into the JUnit Jupiter framework, supporting both static containers (shared between test methods) and instance containers (started/stopped per test method).

Package Information

  • Package Name: org.testcontainers:junit-jupiter
  • Package Type: Maven
  • Language: Java
  • Installation:
    • Maven:
      <dependency>
          <groupId>org.testcontainers</groupId>
          <artifactId>junit-jupiter</artifactId>
          <version>1.21.3</version>
          <scope>test</scope>
      </dependency>
    • Gradle:
      testImplementation 'org.testcontainers:junit-jupiter:1.21.3'

Core Imports

import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.EnabledIfDockerAvailable;

Basic Usage

import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;

@Testcontainers
class MyTestcontainersTests {

    // Shared between test methods - started once, stopped after all tests
    @Container
    private static final MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0");

    // Started before and stopped after each test method
    @Container
    private PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:13")
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("test");

    @Test
    void testContainersAreRunning() {
        assertTrue(mysql.isRunning());
        assertTrue(postgres.isRunning());
    }
}

Architecture

The JUnit Jupiter extension integrates with JUnit 5's extension model through several key components:

  • Annotation Processing: Scans test classes for @Container annotated fields and manages their lifecycle
  • Extension Hooks: Implements JUnit's BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, and ExecutionCondition for precise container lifecycle control
  • Conditional Execution: Provides execution conditions to skip or disable tests when Docker is unavailable
  • Parallel Support: Enables parallel container startup for improved test performance when configured
  • Lifecycle Integration: Connects with TestLifecycleAware containers to provide test context information

Capabilities

Container Lifecycle Management

Automatically manages Docker container startup and shutdown through the @Testcontainers annotation and @Container field annotation.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(TestcontainersExtension.class)
@Inherited
public @interface Testcontainers {
    /**
     * Whether tests should be disabled (rather than failing) when Docker is not available.
     * @return if the tests should be disabled when Docker is not available
     */
    boolean disabledWithoutDocker() default false;

    /**
     * Whether containers should start in parallel.
     * @return if the containers should start in parallel
     */
    boolean parallel() default false;
}

@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Container {
}

Container Lifecycle Rules:

  • Static fields with @Container: Shared between all test methods in the class. Started once before any test method executes, stopped after the last test method completes.
  • Instance fields with @Container: Restarted for each individual test method. Started before each test method, stopped after each test method.
  • Container Requirements: Fields annotated with @Container must implement org.testcontainers.lifecycle.Startable interface.

Usage Examples:

@Testcontainers
class ContainerLifecycleExample {
    
    // Shared container - expensive to start, reused across tests
    @Container
    static final PostgreSQLContainer<?> sharedPostgres = 
        new PostgreSQLContainer<>("postgres:13");
    
    // Per-test container - fresh instance for each test
    @Container
    RedisContainer redis = new RedisContainer("redis:6-alpine");
    
    @Test
    void testWithFreshRedis() {
        // redis container is started fresh for this test
        String redisUrl = redis.getRedisURI();
        // ... test logic
    }
    
    @Test 
    void testWithSharedPostgres() {
        // sharedPostgres container was started once and is reused
        String jdbcUrl = sharedPostgres.getJdbcUrl();
        // ... test logic
    }
}

Conditional Test Execution

Provides Docker availability detection and conditional test execution capabilities.

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ExtendWith(EnabledIfDockerAvailableCondition.class)
public @interface EnabledIfDockerAvailable {
}

Docker Availability Options:

  1. Fail when Docker unavailable (default behavior):

    @Testcontainers
    class MyTests {
        // Tests will fail if Docker is not available
    }
  2. Disable tests when Docker unavailable:

    @Testcontainers(disabledWithoutDocker = true)
    class MyTests {
        // Tests will be skipped if Docker is not available
    }
  3. Method-level Docker requirement:

    class MyTests {
        
        @Test
        @EnabledIfDockerAvailable
        void testRequiringDocker() {
            // This test only runs if Docker is available
        }
        
        @Test
        void testNotRequiringDocker() {
            // This test always runs
        }
    }

Extension Integration

The extension integrates with JUnit Jupiter's lifecycle and provides access to the underlying extension functionality.

public class TestcontainersExtension
    implements BeforeEachCallback, BeforeAllCallback, AfterEachCallback, AfterAllCallback, ExecutionCondition {
    
    /**
     * Check if Docker is available on the system
     * @return true if Docker client can be created and accessed
     */
    public boolean isDockerAvailable();
}

Parallel Container Startup:

@Testcontainers(parallel = true)
class ParallelStartupExample {
    
    @Container
    static final PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:13");
    
    @Container  
    static final MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0");
    
    @Container
    static final RedisContainer redis = new RedisContainer("redis:6-alpine");
    
    // All three containers will start in parallel, reducing total startup time
}

Test Lifecycle Integration:

For containers implementing org.testcontainers.lifecycle.TestLifecycleAware, the extension provides test context:

// Container receives test lifecycle callbacks
public class MyCustomContainer extends GenericContainer<MyCustomContainer> 
    implements TestLifecycleAware {
    
    @Override
    public void beforeTest(TestDescription description) {
        // Called before each test method
        // description provides test ID and filesystem-friendly name
    }
    
    @Override
    public void afterTest(TestDescription description, Optional<Throwable> throwable) {
        // Called after each test method
        // throwable contains test failure information if test failed
    }
}

Error Handling

Common Configuration Errors:

  • ExtensionConfigurationException: Thrown when @Container field does not implement Startable interface
  • ExtensionConfigurationException: Thrown when @Container field is null (containers must be initialized)
  • ExtensionConfigurationException: Thrown when @Testcontainers annotation is not found on class hierarchy

Docker Availability Handling:

  • When disabledWithoutDocker = false (default): Tests fail with Docker connection errors if Docker is unavailable
  • When disabledWithoutDocker = true: Tests are marked as disabled/skipped if Docker is unavailable
  • @EnabledIfDockerAvailable: Individual tests/classes are skipped if Docker is unavailable

Integration Requirements

JUnit Jupiter: Requires JUnit Jupiter 5.x (junit-jupiter-api dependency) Testcontainers Core: Depends on org.testcontainers:testcontainers core library Docker: Requires Docker daemon running and accessible to the test process

Inheritance Support: The @Testcontainers annotation is @Inherited, so subclasses automatically inherit the extension behavior from parent test classes.