Localstack: An implementation of AWS which runs locally with natively or in a docker container
TestContainers: A java library that lets a docker container be run locally for testing
Here TestContainers is used to start the localstack docker image so that the AWS calls can be made against it.
Maven dependencies
Using the v2 dependencies for the AWS library requires bringing in the AWS bom (bill of materials) so that any dependency can just be declared and the bom takes care of getting the correct versions of each dependency. In the example below the S3 and SQS dependencies are configured.Dependency management & dependencies
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.4.11</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sqs</artifactId>
</dependency>
Test dependencies:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.10.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>localstack</artifactId>
<version>1.10.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cloud.localstack</groupId>
<artifactId>localstack-utils</artifactId>
<version>0.1.18</version>
<scope>test</scope>
</dependency>
AWS Configuration
The normal spring configuration for aws clients is very straight forward. Here is an example of an S3Client and an SqsClient using the AWS v2 objects.import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.sqs.SqsClient;
@Configuration
public class AwsConfiguration {
@Bean
public S3Client s3Client(){
return S3Client.builder().region(Region.EU_WEST_1).build();
}
@Bean
public SqsClient sqsClient(){
return SqsClient.builder().region(Region.EU_WEST_1).build();
}
}
These objects will use the default AwsCredentialProvider but this can be overridden here.
TestConfiguration
To create the test configuration we need to start Localstack using TestContainers. This test configuration starts the Localstack and then uses it to configure the S3Client and SqsClient to point to localstackimport static org.testcontainers.containers.localstack.LocalStackContainer.Service.S3;
import static org.testcontainers.containers.localstack.LocalStackContainer.Service.SQS;
import java.net.URI;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.wait.strategy.DockerHealthcheckWaitStrategy;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain;
import software.amazon.awssdk.auth.credentials.ContainerCredentialsProvider;
import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.auth.credentials.SystemPropertyCredentialsProvider;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.CreateQueueRequest;
@TestConfiguration
public class AwsConfigurationTest {
@Bean
public LocalStackContainer localStackContainer() {
LocalStackContainer localStackContainer = new LocalStackContainer().withServices(SQS, S3);
localStackContainer.start();
return localStackContainer;
}
@Bean
public S3Client s3Client() {
final S3Client client = S3Client.builder()
.endpointOverride(URI.create(localStackContainer().getEndpointConfiguration(S3).getServiceEndpoint()))
.build();
client.createBucket(CreateBucketRequest.builder().bucket("test_bucket").build());
return client;
}
@Bean
public SqsClient sqsClient() {
final SqsClient sqs = SqsClient.builder()
.endpointOverride(URI.create(localStackContainer().getEndpointConfiguration(SQS).getServiceEndpoint()))
.build();
sqs.createQueue(CreateQueueRequest.builder().queueName("test_queue").build());
return sqs;
}
}
cool
ReplyDelete