Configuration
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.
Merci
6 Réponses :
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 a >
Vous pouvez également, assez facilement, transmettre l'événement au gestionnaire dans votre test.
Bien que la simulation soit une option viable, vous pouvez également envisager de tester e2e avec un compte aws dédié, trouver quelques exemples, notamment dynamodb et la passerelle api
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.
Bien que cette question soit un peu ancienne. J'étais également confronté au même problème et j'ai trouvé des ressources ci-dessous. Le mettre ici pour le bénéfice des autres. Ces ressources montrent comment écrire des lambdas savoureuses en golang.
https: // ewanvalentine .io / comment-j'écris-les-services-sans-serveur-en-golang-ces-jours / Code - https://github.com/EwanValentine/serverless-api-example < / p>
https: // dev.to/prozz/serverless-in-go-how-to-write-testable-lambdas-4925 Code - https://dev.to/ prozz / serverless-in-go-how-to-write-testable-lambdas-4925
https://github.com/jboursiquot/serverless-go-orchestration-on-aws-course/wiki/Hands-On:-Writing-and-testing-your-Go-Lambdas < / a> Code - https://github.com/jboursiquot/shoutouts
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
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)