I have an AWS Serverless API that performs CRUD operations on a DynamoDB table. The functions work as expected, but I am having trouble trying to add unit tests to support our CI/CD pipeline. The tests fail because they can't create the DynamoDB context and I don't want them to as they would be integration tests. How can I refactor the function so that I can mock IDynamoDBContext
and/or write a test for this function?
Note: I am using Nunit and NSubstitute for testing. I'm open to other testing libraries if it makes this easier. I have seen examples of mocking IDynamoDBContext
and subclassing AsyncSearch
, but I can't inject IDynamoDBContext
so that will not work with the code as written.
A simplified version of my Read Lambda function currently looks like this:
using System.Text.Json;using Amazon.DynamoDBv2;using Amazon.DynamoDBv2.DataModel;using Amazon.Lambda.APIGatewayEvents;using Amazon.Lambda.Core;using Tenants.Domain.Entities;// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]namespace Tenants.Read;public class ReadFunction{ public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context) { string response; int statusCode = 200; try { DynamoDBContext dbContext = CreateDynamoDbContext(); List<Tenant> tenants = await dbContext.ScanAsync<Tenant>([]).GetRemainingAsync(); response = JsonSerializer.Serialize(tenants); } catch (Exception ex) { statusCode = 500; response = JsonSerializer.Serialize(ex.Message); } return new APIGatewayProxyResponse { Body = response, StatusCode = statusCode, Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } } }; } private static DynamoDBContext CreateDynamoDbContext() { AmazonDynamoDBConfig config = new() { AuthenticationRegion = "us-east-1" }; AmazonDynamoDBClient client = new(config); return new DynamoDBContext(client); }}
The beginning of my unit test looks like this:
using System.Text.Json;using Amazon.Lambda.APIGatewayEvents;using Amazon.Lambda.TestUtilities;using NUnit.Framework;namespace Tenants.Read.Tests;[TestFixture]public class ReadFunctionTest{ [Test] public async Task FunctionHandler_Returns200() { // Arrange var function = new ReadFunction(); var context = new TestLambdaContext(); var request = new APIGatewayProxyRequest(); // Act APIGatewayProxyResponse response = await function.FunctionHandler(request, context); // Assert Assert.That(response.StatusCode, Is.EqualTo(200)); }}