Testcontainers
Use Testcontainers with LocalStack
3 minute read
Overview
Testcontainers is a library that helps you to run your tests against real dependencies.
In this guide, you will learn how to use Testcontainers with LocalStack.
Covered Topics
- Installing the Localstack module
- Obtaining a LocalStack container
- Configuring the AWS client
- Special Setup for using RDS
- Useful Links
Installing the Localstack module
dotnet add package Testcontainers.LocalStack --version 3.0.0
go get github.com/testcontainers/testcontainers-go/modules/localstack
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>localstack</artifactId>
<version>1.18.0</version>
<scope>test</scope>
</dependency>
testImplementation 'org.testcontainers:localstack:1.18.0'
npm i @testcontainers/localstack
Obtaining a LocalStack container
var localStackContainer = new LocalStackBuilder().Build();
await localStackContainer.StartAsync()
.ConfigureAwait(false);
container, err := localstack.StartContainer(ctx, localstack.NoopOverrideContainerRequest)
LocalStackContainer localstack = new LocalStackContainer(DockerImageName.parse("localstack/localstack:3"));
const localstack = new LocalstackContainer("localstack/localstack:3").start()
Configuring the AWS client
var config = new AmazonS3Config();
config.ServiceURL = localStackContainer.GetConnectionString();
using var client = new AmazonS3Client(config);
func s3Client(ctx context.Context, l *localstack.LocalStackContainer) (*s3.Client, error) {
// the Testcontainers Docker provider is used to get the host of the Docker daemon
provider, err := testcontainers.NewDockerProvider()
if err != nil {
return nil, err
}
host, err := provider.DaemonHost(ctx)
if err != nil {
return nil, err
}
mappedPort, err := l.MappedPort(ctx, nat.Port("4566/tcp"))
if err != nil {
return nil, err
}
customResolver := aws.EndpointResolverWithOptionsFunc(
func(service, region string, opts ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{
PartitionID: "aws",
URL: fmt.Sprintf("http://%s:%d", host, mappedPort.Int()),
SigningRegion: region,
}, nil
})
awsCfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
config.WithEndpointResolverWithOptions(customResolver),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accesskey, secretkey, token)),
)
if err != nil {
return nil, err
}
client := s3.NewFromConfig(awsCfg, func(o *s3.Options) {
o.UsePathStyle = true
})
return client, nil
}
S3Client s3 = S3Client.builder()
.endpointOverride(localstack.getEndpoint())
.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(localstack.getAccessKey(), localstack.getSecretKey())))
.region(Region.of(localstack.getRegion()))
.build();
const awsConfig = {
endpoint: localstack.getConnectionUri(),
credentials: {
accessKeyId: "test",
secretAccessKey: "test",
},
region: "eu-central-1",
};
const s3 = S3Client(awsConfig);
Special Setup for using RDS
Some services like RDS require additional setup so that the correct port is exposed and accessible for the tests.
The reserved ports on LocalStack are between 4510-4559
, depending on your use case you might need to expose several ports using witExposedPorts
.
Check the pro-sample on how to use RDS with Testcontainers for Java.
The Testcontainer can be created like this:
/**
* Start LocalStackContainer with exposed Ports. Those ports are used by services like RDS, where several databases can be started, running on different ports.
* In this sample we only map 5 ports, however, depending on your use case you may need to map ports up to 4559
*/
@Rule
public LocalStackContainer localstack = new LocalStackContainer(DockerImageName("localstack/localstack:2.0.0"))
.withExposedPorts(4510, 4511, 4512, 4513, 4514) // the port can have any value between 4510-4559, but LS starts from 4510
.withEnv("LOCALSTACK_AUTH_TOKEN", auth_token); // add your Auth Token here
To find the exposed port which you can use to connect to the instance:
// identify the port localstack provides for the instance
int localstack_port = response.dbInstance().endpoint().port();
// get the port it was mapped to, e.g. the one we can reach from host/the test
int mapped_port = localstack.getMappedPort(localstack_port);
Useful Links
- https://www.testcontainers.com (Java, .NET, Go, Python, Ruby, Node.js)
- https://www.testcontainers.org (Java)
- https://www.testcontainers.org/modules/localstack (Java)
- https://golang.testcontainers.org (Go)
- https://golang.testcontainers.org/modules/localstack (Go)
- https://node.testcontainers.org (NodeJs)
- https://node.testcontainers.org/modules/localstack (NodeJs)