1. Overview
AWS TestKit provides a set of JUnit 5 extensions to make testing with AWS SDK easier. AWS TestKit works with service mocks provided by tools like LocalStack, DynamoDB Local, or even real AWS services.
Only AWS SDK for Java 2.x is supported. Version 1.x will not be supported.
Currently, the following services are supported:
-
CloudFormation
-
DynamoDB
-
Firehose
-
Kinesis
-
KMS
-
S3
-
SecretsManager
-
SES
-
SNS
-
SQS
2. Configuration
AWS TestKit provides an endpoint resolver mechanism to resolve endpoint configuration values for the AWS SDK clients. To provide values for configuration you need to implement an EndpointResolver
. However, if you are using the LocalStack extension, the endpoint configuration can be omitted.
import com.github.awstestkit.Endpoint;
import com.github.awstestkit.EndpointResolver;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.extension.ExtensionContext;
import java.net.URI;
import java.net.URISyntaxException;
public class MyEndpointResolver implements EndpointResolver {
@NotNull
@Override
public Endpoint resolveEndpoint(@NotNull ExtensionContext extensionContext) {
return new Endpoint() {
@NotNull
@Override
public URI url() throws URISyntaxException {
return new URI(System.getenv("AWS_URL"));
}
@NotNull
@Override
public String region() {
return System.getenv("AWS_REGION");
}
@NotNull
@Override
public String accessKey() {
return System.getenv("AWS_ACCESS_KEY");
}
@NotNull
@Override
public String secretKey() {
return System.getenv("AWS_SECRET_KEY");
}
};
}
}
The endpoint resolver has to be added to the test using the @AwsEndpoint
annotation. To inject AWS SDK clients to the test you can use the @AwsClient
annotation.
import com.github.awstestkit.AwsClient;
import com.github.awstestkit.AwsEndpoint;
import com.github.awstestkit.sns.junit5.SnsTest;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.services.sns.SnsClient;
import static java.util.Collections.emptyList;
import static org.junit.jupiter.api.Assertions.assertIterableEquals;
@SnsTest
@AwsEndpoint(endpointResolver = MyEndpointResolver.class)
class CustomEndpointTest {
@Test
void getTopics(@AwsClient SnsClient client) {
assertIterableEquals(client.listTopics().topics(), emptyList());
}
}
The client injection only works if you have annotated the test with one of service test annotations such as @SnsTest
.
3. LocalStack Extension
Using the @LocalStackTest
annotation will start up LocalStack using Testcontainers for your tests. You can pass the required services
as an argument.
If any of the service extensions (e.g. @DynamoDbTest
, @SnsTest
) has been provided, then the services
argument can be omitted.
@LocalStackTest
@SnsTest
class LocalStackExtensionTest {
@Test
void localStackIsRunning(@AwsClient SnsClient client) {
assertIterableEquals(client.listTopics().topics(), emptyList());
}
}
You don’t need to configure an endpoint resolver when using the LocalStack extension. The extension will automatically configure an LocalStackEndpointResolver
that works with the LocalStack container it starts.
4. CloudFormation Extension
The CloudFormation extension allows you to create CloudFormation stacks inside your tests. If you already have your infrastructure described as CloudFormation templates you can then reuse some of those templates in your tests.
@LocalStackTest
@CloudFormationTest
@CfnStacks(
@CfnStack(name = "awstestkit-stack", templateFile = "src/test/resources/template.yml")
)
class CloudFormationExtensionTest {
@Test
void setupStacks(@AwsClient CloudFormationClient client) {
assertFalse(client.listStacks().stackSummaries().isEmpty());
}
}
5. DynamoDB Extension
The DynamoDB extension allows you to create DynamoDB tables inside your tests.
@LocalStackTest
@DynamoDbTest
@DynamoDbTables(
@DynamoDbTable(
tableName = "table",
keySchema = @DynamoDbKeySchemaElement(
attributeName = "id",
keyType = KeyType.HASH
),
attributeDefinitions = @DynamoDbAttributeDefinition(
attributeName = "id",
attributeType = ScalarAttributeType.S
)
)
)
class DynamoDbExtensionTest {
@Test
void setupTables(@AwsClient DynamoDbClient client) {
assertFalse(client.listTables().tableNames().isEmpty());
}
}
6. S3 Extension
The S3 extension allows you to create S3 buckets and objects inside your tests.
@LocalStackTest
@S3Test
@S3Bucket("com-github-awstestkit-bucket")
@S3Objects(
@S3Object(
bucketName = "com-github-awstestkit-bucket",
key = "/path/to/file",
content = "content"
)
)
class S3ExtensionTest {
@Test
void setupBuckets(@AwsClient S3Client client) {
assertFalse(client.listBuckets().buckets().isEmpty());
}
}
7. SecretsManager Extension
The SecretsManager extension allows you to create SecretsManager secrets your tests.
@LocalStackTest
@SecretsManagerTest
@Secrets(
@Secret(name = "SecretName", value = "SecretValue")
)
public class SecretsManagerExtensionTest {
@Test
void setupSecrets(@AwsClient SecretsManagerClient client) {
assertFalse(client.listSecrets().secretList().isEmpty());
}
}
8. SNS Extension
The SNS extension allows you to create SNS topics inside your tests.
@LocalStackTest
@SnsTest
@SnsTopic("TopicName")
class SnsExtensionTest {
@Test
void setupTopics(@AwsClient SnsClient client) {
assertFalse(client.listTopics().topics().isEmpty());
}
}
If you need to use the ARN of a created topic, you can inject it to your test with the @TopicArn
annotation.
@LocalStackTest
@SnsTest
@SnsTopic("TopicName")
class SnsTopicArnTest {
@Test
void setupTopics(@AwsClient SnsClient client, @TopicArn("TopicName") String topicArn) {
GetTopicAttributesRequest request = GetTopicAttributesRequest.builder()
.topicArn(topicArn)
.build();
assertTrue(client.getTopicAttributes(request).hasAttributes());
}
}
9. SQS Extension
The SQS extension allows you to create SQS queues inside your tests.
@LocalStackTest
@SqsTest
@SqsQueue("QueueName")
class SqsExtensionTest {
@Test
void setupQueues(@AwsClient SqsClient client) {
assertFalse(client.listQueues().queueUrls().isEmpty());
}
}
If you need to use the URL of a created queue, you can inject it to your test with the @QueueUrl
annotation.
@LocalStackTest
@SqsTest
@SqsQueue("QueueName")
class SqsQueueUrlTest {
@Test
void setupQueues(@AwsClient SqsClient client, @QueueUrl("QueueName") String queueUrl) {
GetQueueAttributesRequest request = GetQueueAttributesRequest.builder()
.queueUrl(queueUrl)
.attributeNames(QueueAttributeName.ALL)
.build();
assertFalse(client.getQueueAttributes(request).attributes().isEmpty());
}
}