DEV Community

Cover image for Integration tests for AWS serverless solution
ohalay
ohalay

Posted on

Integration tests for AWS serverless solution

Motivation

  1. Add integration tests without fakes for AWS services.
  2. Run tests locally and in a build machine without AWS accounts.

Application architecture

We have a typical serverless solution - lambda that is triggered by AWS resource and store result in the S3 bucket. It ia two popular AWS serverless services.

Integration tests solution

You need to make sure that Lambda put documents into an S3 bucket. This implementation consists of the next concepts:

  • xUnit unit tests tool
  • lambda with configured dependecy injection
  • s3 bucket that runs in docker using LocalStack

Run container

To launch a container in code we will use Testcontainers. Testcontainers is a library that is built on top of the .NET Docker remote API and provides a lightweight implementation to support your test environment in all circumstances. This library supports pre-defined packages for containers or you can use your .dockerfile. We will use a pre-defined package for LocalStak. LocalStack is a cloud service emulator that runs in a single container for AWS service. LocalStack supports a growing number of AWS services.

var container = new LocalStackBuilder()
  .Build();
Enter fullscreen mode Exit fullscreen mode

Configure xUnit with container

You need to start the container before the tests run and stop after the tests run. To do that we will use two features IAsyncLifetime and IClassFixture. And next, add access to the container(local URLs) in tests.

public class LocalStackFixture : IAsyncLifetime
{
  public readonly LocalStackContainer Container =
    new LocalStackBuilder().Build();

  public Task DisposeAsync()
    => container.StopAsync();

  public Task InitializeAsync()
    => container.StartAsync();
}

public class LambdaHandlerTest : IClassFixture<LocalStackFixture>
{
  private readonly LocalStackFixture fixture;

  public LambdaHandlerTest(LocalStackFixture localStackFixture)
    => fixture = localStackFixture;
}
Enter fullscreen mode Exit fullscreen mode

Initialize AWS service

You need to have a pre-defined S3 bucket, before putting documents. LocalStck has built-in AWS CLI(awslocal). The awslocal command has the same usage as the aws command. For detailed usage, please refer to the man pages of aws help, but of course, it has some limitations 😉. That means, we just need to run create bucket command and start running the test when a command is completed.

public LocalStackContainer Container = new LocalStackBuilder()
  .WithStartupCallback((container, ct) => 
    container.ExecAsync(new[] 
    {
     "awslocal", "s3api", "create-bucket", "--bucket", BUCKETNAME 
    }, ct))
  .Build();
Enter fullscreen mode Exit fullscreen mode

Lambda Tests

The final test with all configurations will look like that

[Fact]
public async Task HandleShoudPutDocToS3Test()
{
  var client = new AmazonS3Client(new AmazonS3Config 
  { 
    ServiceURL = fixture.Container.GetConnectionString() 
  });

  var sut = new LambdaHandler(collection => collection
    .AddSingleton<IAmazonS3>(client)
    .PostConfigure<Config>(c => c.BucketName =
       LocalStackFixture.BUCKETNAME));

  var docId = Guid.NewGuid().ToString();
  await sut.Handle(new TestLambdaContext 
  {
    AwsRequestId = docId 
  });

  var res = await client.GetObjectAsync(
    LocalStackFixture.BUCKETNAME,
    $"{docId}.txt");
  _ = res.HttpStatusCode.Should().Be(HttpStatusCode.OK);
}
Enter fullscreen mode Exit fullscreen mode

Conclusions

  1. To run tests locally or in the build machine we only need to install docker and run standard tests command dotnet test.
  2. Testcontainers - support a loot of pre-defined packages that you can use the integration tests.
  3. LocalStack makes development easier and cheaper when work with AWS services.

And finally, the source code in the GitHub repository

Build&Test GitHub repo size GitHub contributors GitHub stars GitHub forks

Serverless integration tests

A public feed with available products that updates every day

Business problem

  • Integration tests for serverless solution

Requirements

  • Docker

Implementation

  1. S3 public buckets with available documents
  2. Lambda updates document

Help links

Top comments (0)