在 AWS Lambda 单元测试中模拟 DynamoDB

问题描述 投票:0回答:1

我有一个 AWS Serverless API,可以对 DynamoDB 表执行 CRUD 操作。这些功能按预期工作,但我在尝试添加单元测试来支持我们的 CI/CD 管道时遇到了麻烦。测试失败是因为它们无法创建 DynamoDB 上下文,而且我不希望它们这样做,因为它们将是集成测试。如何重构该函数以便我可以模拟

IDynamoDBContext
和/或为此函数编写测试?

注意:我使用 Nunit 和 NSubstitute 进行测试。如果其他测试库能让这变得更容易,我愿意接受。我见过模拟

IDynamoDBContext
和子类化
AsyncSearch
的示例,但我无法注入
IDynamoDBContext
,因此这不适用于编写的代码。

我的 Read Lambda 函数的简化版本目前如下所示:

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);
    }
}

我的单元测试的开头是这样的:

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));
    }
}
c# aws-lambda amazon-dynamodb nunit aws-serverless
1个回答
0
投票

您可以使用 Lambda 添加第二个参数化函数构造函数,并在那里执行 DI 进行测试。

查看 AWS 的这篇文章,其中显示了数据库依赖性(在“测试工具”标题下): https://docs.aws.amazon.com/lambda/latest/dg/dotnet-csharp-testing.html

在您的场景中,它将包括类似以下内容:

private readonly IDynamoDBContext _dbContext

public ReadFunction(IDynamoDBContext dbContext)
{
    _dbContext = dbContext;
}

然后你可以用以下方法来嘲笑它:

[TestFixture]
public class ReadFunctionTest
{
    [Test]
    public async Task FunctionHandler_Returns200()
    {
        var mockDynamoDBContext = new DynamoDBContext(Substitute.For<IAmazonDynamoDB>());
        var context = new TestLambdaContext();
        var function = new ReadFunction(mockDynamoDBContext);

© www.soinside.com 2019 - 2024. All rights reserved.