簡體   English   中英

如何對使用 AWS SDK 為 Go V2 實施的 Lambda 進行單元測試

[英]How to Unit Test a Lambda Implemented with AWS SDK for Go V2

給定以下簡單的 lambda 寫在 Go 中,它只返回一個表描述......

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) {
    
    ...
}

func main() {
   s := session.Must(session.NewSession())
   d := deps {
       svc: dynamodb.New(s),
       table: dynamoDBTableName,
   }

   lambda.Start(d.handler)
}

鑒於我需要上下文來加載 dynamodb.NewFromConfig 所需的配置,我如何測試使用新 AWS SDK 為 Go V2 編寫的dynamodb.NewFromConfig

首先讓你的處理程序成為一個不起眼的 object,這樣我們就可以“跳過”測試它:

func handler(ctx context.Context, req events.APIGatewayProxyRequest) 
    (events.APIGatewayProxyResponse, error) {
    dynamoWrapper := &RealDynamoWrapper{}
    proxyController := &ProxyController{DynamoWrapper: dynamoWrapper}
    return proxyController.proxy(ctx, req)

這個想法是通過將所有復雜性委托給proxyController來使處理程序 function 變得謙虛。

現在,讓我們考慮要測試的ProxyController ,我們需要先定義它:

type 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
}

現在這個包裝器的真正實現,上面提到的RealDynamoWrapper將像您對 sdk 一樣進行調用。不過對於我們的測試,我們需要一個模擬實現:

type 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...)
}

最后,在您的測試中,您現在可以模擬 dynamo 調用:

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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM