猿问

如何对使用适用于 Go V2 的 AWS 开发工具包实现的 Lambda 进行单元测试

给定以下用 Go 编写的简单 lambda,它只返回一个表描述...


package main


import (

    "context"

    "encoding/json"

    "fmt"

    "log"

    "net/http"

    "os"

    "strings"


    "github.com/aws/aws-lambda-go/events"

    "github.com/aws/aws-lambda-go/lambda"

    "github.com/aws/aws-sdk-go-v2/aws"

    "github.com/aws/aws-sdk-go-v2/config"

    "github.com/aws/aws-sdk-go-v2/service/dynamodb"

    "go.uber.org/zap"

)


var (

    dynamoDBTableName = aws.String(os.Getenv(EnvDynamoDBTableName))


    logger = func() *zap.Logger {

        l, err := zap.NewProduction()

        if err != nil {

            log.Printf("failed to create zap logger: %v", err)

        }

        return l

    }()

)


func handler(ctx context.Context, req events.APIGatewayProxyRequest) 

    (events.APIGatewayProxyResponse, error) {


    defer logger.Sync()


    resp := events.APIGatewayProxyResponse{}


    cfg, err := config.LoadDefaultConfig(ctx)

    if err != nil {

        logger.Error("failed to load AWS config", zap.Error(err))

        return resp, fmt.Errorf("failed to load AWS config: %w", err)

    }


    svc := dynamodb.NewFromConfig(cfg)


    // fake logic

    t, err := svc.DescribeTable(ctx, &dynamodb.DescribeTableInput{TableName: dynamoDBTableName})

    if err != nil {

        logger.Error("failed to describe table", zap.String("table-name", *dynamoDBTableName), zap.Error(err))

    }

    var sb strings.Builder

    enc := json.NewEncoder(&sb)

    err = enc.Encode(t.Table)

    if err != nil {

        logger.Error("failed to JSON encode response", zap.Error(err))

    }

    resp.Body = sb.String()

    resp.StatusCode = http.StatusOK


    return resp, nil

}


func main() {

   lambda.Start(handler)

}

...如何在本地对其进行单元测试?使用旧的SDK,可以使用如下依赖注入:


type deps struct 

    svc dynamodbiface.DynamoDBAPI

    table string

}


func (d *deps) handler(ctx context.Context, req events.APIGatewayProxyRequest) 

    (events.APIGatewayProxyResponse, error) {

    

    ...

}


如何测试使用新的适用于 Go V2 的 AWS 开发工具包编写的 lambda,因为我需要上下文来加载所需的配置?dynamodb.NewFromConfig


汪汪一只猫
浏览 82回答 1
1回答

犯罪嫌疑人X

首先,使你的处理程序成为一个不起眼的对象,这样我们就可以“跳过”测试它:func handler(ctx context.Context, req events.APIGatewayProxyRequest)     (events.APIGatewayProxyResponse, error) {    dynamoWrapper := &RealDynamoWrapper{}    proxyController := &ProxyController{DynamoWrapper: dynamoWrapper}    return proxyController.proxy(ctx, req)这个想法是使处理程序函数变得谦卑,方法是让它将所有复杂性委托给 .proxyController现在,让我们考虑要测试的,我们需要先定义它:ProxyControllertype ProxyController struct {  dynamoWrapper DynamoWrapper}func(controller *ProxyController) Proxy(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {  // this is where your implementation lives that you need to mock stuff for  // We are mocking this line from your question  svc := controller.dynamoWrapper.NewFromConfig(...)  // do other stuff and then return something  return events.APIGatewayProxyResponse{}, nil}你可以看到我将依赖于一个包装版本的dynamo,它看起来像这样:type DynamoWrapper interface {  NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client}现在,此包装器的真正实现,上面引用的那个将像对 sdk 执行操作一样进行调用。但是,对于我们的测试,我们想要一个模拟实现:RealDynamoWrappertype mockDynamoWrapper struct {  NewFromConfigFunc func(aws.Config, ...func(*Options)) *Client}func(dynamoWrapper *mockDynamoWrapper) NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client {  return dynamoWrapper.NewFromConfigFunc(cfg, optFns...)}最后,在测试中,您现在可以模拟发电机调用:func TestProxyController(t *testing.T) {  // given  dynamoWrapper := &mockDynamoWrapper{}  proxyController := &ProxyController{DynamoWrapper: mockDynamoWrapper}  request := events.APIGatewayProxyRequest{}  dynamoWrapper.NewFromConfigFunc = func(aws.Config, ...func(*Options)) *Client {    // setup your mock function to do whatever you want  }  // when  proxyController.proxy(context.Background, request)  // then do your asserts}
随时随地看视频慕课网APP

相关分类

Go
我要回答