Testcontainers module for LocalStack - AWS cloud stack emulation
npx @tessl/cli install tessl/maven-org-testcontainers--localstack@1.21.1The LocalStack Testcontainers module provides a Java library that enables developers to create and manage LocalStack containers for testing AWS service integrations. LocalStack is a fully functional local AWS cloud stack emulator that allows developers to develop and test cloud and serverless applications locally without connecting to actual AWS services.
This module wraps LocalStack in a Docker container managed by Testcontainers, providing a simple Java API to start LocalStack instances with specific AWS services enabled (S3, SQS, Lambda, DynamoDB, etc.), configure endpoints and credentials, and integrate seamlessly with JUnit tests.
Required Dependencies:
org.testcontainers:localstack (this package)org.testcontainers:testcontainers is required (provided transitively)Default Behaviors:
4566 (LocalStack edge port, automatically exposed and mapped to random host port)localstack/localstack:2.0 or localstack/localstack:latest)"test", secret key "test" (can be overridden via environment variables)"us-east-1" (can be overridden via DEFAULT_REGION environment variable)withServices() for versions < 0.13; optional for versions >= 0.13)start() returnsgetEndpoint() to retrieve)Threading Model:
start() method blocks until container is readystop() method blocks until container is stoppedLifecycle:
localstack.start() before usestart() returnslocalstack.stop() for cleanupstop() even on errors@ClassRule or @Container for automatic lifecycle management (recommended)getEndpoint() and credential methods can only be called after start() completesExceptions:
ContainerLaunchException - Container failed to start (timeout, image pull failure, etc.)IllegalStateException - Called getEndpoint() before container started, or network configuration errorIllegalArgumentException - Invalid Docker image name or service configurationPortBindingException - Port binding conflictsDockerNotAvailableException - Docker daemon not accessibleImagePullException - Failed to pull Docker imageTimeoutException - Container startup timeout (container started but not ready)SdkClientException (SDK v2) - Connection failures, authentication errorsAmazonClientException (SDK v1) - Connection failures, authentication errorsEdge Cases:
withStartupTimeout())withReuse(true) to reuse containers across test runs (requires testcontainers configuration)withNetwork() and withNetworkAliases() for multi-container testsgetEndpointOverride(Service) for service-specific endpointsgetEndpoint() returns IP address to ensure path-style access works correctlygetAccessKey() after start to verifyDEFAULT_REGION environment variable overrides default regionwithNetworkAliases() is used as HOSTNAME_EXTERNAL or LOCALSTACK_HOSTgetEndpoint() resolves hostname to IP; may fail if DNS resolution issuesgetEndpointOverride(Service)S3_SKIP_SIGNATURE_VALIDATION=1 for some SDK configurationsLOCALSTACK_API_KEY environment variable for Pro featuresCommon Pitfalls:
start() before using container (causes IllegalStateException)getEndpoint())IllegalStateException from getEndpoint() if container fails to startlocalhost in endpoint URL (should use IP from getEndpoint())<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>localstack</artifactId>
<version>1.21.4</version>
<scope>test</scope>
</dependency>For Gradle:
testImplementation 'org.testcontainers:localstack:1.21.4'import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.localstack.LocalStackContainer.Service;
import org.testcontainers.containers.localstack.LocalStackContainer.EnabledService;
import org.testcontainers.utility.DockerImageName;import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.localstack.LocalStackContainer.Service;
import org.testcontainers.utility.DockerImageName;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
// Create and start LocalStack container
LocalStackContainer localstack = new LocalStackContainer(
DockerImageName.parse("localstack/localstack:2.0")
)
.withServices(Service.S3, Service.SQS);
localstack.start();
try {
// Get configuration for AWS SDK clients
String endpoint = localstack.getEndpoint().toString();
String accessKey = localstack.getAccessKey();
String secretKey = localstack.getSecretKey();
String region = localstack.getRegion();
// Use with AWS SDK v2
S3Client s3 = S3Client.builder()
.endpointOverride(localstack.getEndpoint())
.credentialsProvider(
StaticCredentialsProvider.create(
AwsBasicCredentials.create(accessKey, secretKey)
)
)
.region(Region.of(region))
.build();
// Create a bucket and use S3
s3.createBucket(b -> b.bucket("test-bucket"));
} finally {
localstack.stop();
}import org.junit.ClassRule;
import org.junit.Test;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.localstack.LocalStackContainer.Service;
import org.testcontainers.utility.DockerImageName;
public class MyAwsIntegrationTest {
@ClassRule
public static LocalStackContainer localstack = new LocalStackContainer(
DockerImageName.parse("localstack/localstack:2.0")
)
.withServices(Service.S3, Service.DYNAMODB, Service.LAMBDA);
@Test
public void testS3Operations() {
// Container automatically started before test
// Test code using localstack.getEndpoint(), etc.
// Container automatically stopped after test
}
}The LocalStack Testcontainers module is built around several key components:
GenericContainer, providing fluent configuration APIThe module automatically adapts to different LocalStack versions:
LOCALSTACK_HOST environment variable (instead of deprecated HOSTNAME_EXTERNAL)Create and configure LocalStack containers with specific services, environment variables, and Docker settings.
/**
* Creates a LocalStack container with the specified Docker image
* @param dockerImageName Docker image name for LocalStack (e.g., "localstack/localstack:2.0")
*/
public LocalStackContainer(DockerImageName dockerImageName);
/**
* Creates a LocalStack container with default image and default tag
* @deprecated Use LocalStackContainer(DockerImageName) instead
*/
@Deprecated
public LocalStackContainer();
/**
* Creates a LocalStack container with default image and specified version
* @param version Version tag for LocalStack
* @deprecated Use LocalStackContainer(DockerImageName) instead
*/
@Deprecated
public LocalStackContainer(String version);
/**
* Declares AWS services to be launched by the container
* @param services One or more Service enum values
* @return This container object for method chaining
*/
public LocalStackContainer withServices(Service... services);
/**
* Declares AWS services using the EnabledService interface (for custom services)
* @param services One or more EnabledService implementations
* @return This container object for method chaining
*/
public LocalStackContainer withServices(EnabledService... services);Retrieve endpoint URLs and credentials for configuring AWS SDK clients to communicate with LocalStack.
/**
* Provides the main endpoint to communicate with LocalStack
* Intended for AWS SDK clients running on the test host
* @return URI endpoint with host IP and mapped port
* @throws IllegalStateException if cannot obtain endpoint URL
*/
public URI getEndpoint();
/**
* Provides endpoint override for a specific service
* Useful in legacy mode where services have different ports
* @param service The AWS service to access
* @return URI endpoint override for the service
* @throws IllegalStateException if cannot obtain endpoint URL
*/
public URI getEndpointOverride(EnabledService service);
/**
* Provides default AWS access key ID for LocalStack
* @return Access key (default: "test", or from AWS_ACCESS_KEY_ID env var)
*/
public String getAccessKey();
/**
* Provides default AWS secret access key for LocalStack
* @return Secret key (default: "test", or from AWS_SECRET_ACCESS_KEY env var)
*/
public String getSecretKey();
/**
* Provides default AWS region for LocalStack
* @return Region (default: "us-east-1", or from DEFAULT_REGION env var)
*/
public String getRegion();Predefined AWS services that can be enabled in LocalStack, with support for custom service names.
/**
* Predefined AWS services supported by LocalStack
*/
public enum Service implements EnabledService {
S3, // Amazon S3 object storage
SQS, // Amazon SQS message queuing
DYNAMODB, // Amazon DynamoDB NoSQL database
LAMBDA, // AWS Lambda serverless functions
SNS, // Amazon SNS pub/sub messaging
KINESIS, // Amazon Kinesis streaming
CLOUDFORMATION, // AWS CloudFormation infrastructure as code
CLOUDWATCH, // Amazon CloudWatch monitoring
CLOUDWATCHLOGS, // Amazon CloudWatch Logs
SECRETSMANAGER, // AWS Secrets Manager
KMS, // AWS Key Management Service
IAM, // AWS Identity and Access Management
STS, // AWS Security Token Service
SSM, // AWS Systems Manager Parameter Store
// ... and more (see full list in documentation)
}
/**
* Interface for enabled services, allows custom service names
*/
public interface EnabledService {
/**
* Returns the LocalStack service name
*/
String getName();
/**
* Returns the port for the service (default: 4566)
*/
default int getPort() {
return 4566;
}
/**
* Creates an EnabledService with a custom name
* @param name The LocalStack service name
* @return EnabledService instance
*/
static EnabledService named(String name);
}Examples and patterns for integrating with AWS SDK v1 and v2.
Advanced Docker networking setup for container-to-container communication.