2
votes

Mock AWS API Gateway demande et DynamoDB pour Golang Lambda Function Unit Test

Configuration

  • Windows 10
  • Passer à la v1.10.3
  • aws cli v1.16.67

Ce que j'essaie de faire

Testez une fonction AWS Lambda écrite à l'aide de golang . La fonction accepte une requête de la API Gateway et effectue ensuite certaines tâches avec DynamoDB . La plupart des informations ci-dessous proviennent de ceci a > article (je suis un débutant avec Go)

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "os"
    "regexp"

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

var uuidRegexp = regexp.MustCompile(`\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b`)
var errorLogger = log.New(os.Stderr, "ERROR ", log.Llongfile)

type job struct {
    ID                string `json:"id"`
    ClientID          string `json:"clientId"`
    Title             string `json:"title"`
    Count             int    `json:"count"`
}

// CreateJobCommand manages interactions with DynamoDB
func CreateJobCommand(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {

    if req.Headers["Content-Type"] != "application/json" {
        return clientError(http.StatusNotAcceptable) //406
    }

    newJob := new(job)
    err := json.Unmarshal([]byte(req.Body), newJob)

    // Ensure request has deserialized correctly
    if err != nil {
        return clientError(http.StatusUnprocessableEntity) //422
    }

    // Validate ID and ClientID attributes match RegEx pattern
    if !uuidRegexp.MatchString(newJob.ID) || !uuidRegexp.MatchString(newJob.ClientID) {
        return clientError(http.StatusBadRequest)
    }

    // Mandatory field check
    if newJob.Title == "" {
        return clientError(http.StatusBadRequest)
    }

    // Put item in database
    err = putItem(newJob) // putItem is defined in another file
    if err != nil {
        return serverError(err)
    }

    return events.APIGatewayProxyResponse{
        StatusCode: 201,
    }, nil
}

// Add a helper for handling errors. This logs any error to os.Stderr
// and returns a 500 Internal Server Error response that the AWS API
// Gateway understands.
func serverError(err error) (events.APIGatewayProxyResponse, error) {
    errorLogger.Println(err.Error())

    return events.APIGatewayProxyResponse{
        StatusCode: http.StatusInternalServerError,
        Body:       http.StatusText(http.StatusInternalServerError),
    }, nil
}

// Similarly add a helper for send responses relating to client errors.
func clientError(status int) (events.APIGatewayProxyResponse, error) {
    return events.APIGatewayProxyResponse{
        StatusCode: status,
        Body:       http.StatusText(status),
    }, nil
}

func putItem(job *job) error {

    // create an aws session
    sess := session.Must(session.NewSession(&aws.Config{
        Region:   aws.String("us-east-1"),
        Endpoint: aws.String("http://localhost:8000"),
    }))

    // create a dynamodb instance
    db := dynamodb.New(sess)

    // marshal the job struct into an aws attribute value object
    jobAVMap, err := dynamodbattribute.MarshalMap(job)
    if err != nil {
        return err
    }

    input := &dynamodb.PutItemInput{
        TableName: aws.String("TEST_TABLE"),
        Item:      jobAVMap,
    }

    _, err = db.PutItem(input)
    return err
}

func main() {
    lambda.Start(CreateJobCommand)
}

Problème

Je veux écrire une série de tests unitaires pour tester cette fonction. Dans mon esprit, la première chose que je dois faire est de simuler la requête API Gateway et la table DynamoDB, mais je ne sais pas comment faire cela.

  1. Y a-t-il un cadre de simulation que je devrais utiliser?
  2. Si quelqu'un connaît une documentation qui pourrait aider sur ce sujet, pourriez-vous la signaler s'il vous plaît? (Mes compétences Google n'en ont pas encore révélé)

Merci


0 commentaires

6 Réponses :


0
votes

Veuillez vérifier si l'exécution de dynamo-db dans un docker ne vous aidera pas à implémenter votre test.

Vérifiez: connexion AWS SAM Local avec dynamodb dans le docker

Vous pouvez également, assez facilement, transmettre l'événement au gestionnaire dans votre test.


0 commentaires


0
votes

En plus de la réponse d'Adrian :

Jetez un œil à LocalStack . Il fournit un cadre de test / simulation facile à utiliser pour développer des applications liées à AWS en activant les API compatibles AWS sur votre machine locale ou dans Docker. Il prend en charge deux douzaines d'API AWS et DynamoDB et Lambda en font partie. C'est vraiment un excellent outil pour les tests fonctionnels sans utiliser un environnement AWS séparé pour cela.


0 commentaires


0
votes

La question est un peu ancienne maintenant, mais vous pouvez exécuter dynamodb localement et l'utiliser module aws-lambda-go-test qui peut exécuter lambda localement et peut être utilisé pour tester la réponse réelle de lambda

Divulgation complète J'ai forké et mis à jour ce module


0 commentaires

4
votes

La façon dont je le fais est de passer les dépendances dans le récepteur du pointeur (puisque la signature du gestionnaire est limitée) et d'utiliser des interfaces. Chaque service a une interface correspondante. Pour dynamodb - dynamodbiface. Donc dans votre cas en lambda lui-même vous devez définir un récepteur:

 type mockDynamo struct {
    dynI dynamodbiface.DynamoDBAPI
    dynResponse dynamodb.PutItemOutput

} 

func (mq mockDynamo) PutItem (in *dynamodb.PutItemInput) (*dynamodb.PutItemOutput , error) {
    return &dynamodv.dynResponse, nil
}


        m1: = mockDynamo {

            dynResponse : dynamodb.PutItemOutput{
            
            some mocked output
        } 


        inj := myReceiver{
            dyn: m1,         
        }

     inj.CreateJobCommand(some mocked data  for APIGateway request)

changez main en:

    _, err = inj.dynI.PutItem(input)

changez le gestionnaire en

func (inj *myReceiver) CreateJobCommand(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)


0 commentaires