设置
我要做什么
测试使用golang
编写的AWS Lambda函数。该函数接受来自API Gateway
的请求,然后对DynamoDB
进行处理。以下内容大部分摘自this文章(我是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)
}
问题
我想编写一组单元测试来测试此功能。在我看来,我要做的第一件事是模拟API网关请求和DynamoDB表,但我不知道如何执行此操作。
问题
谢谢
答案 0 :(得分:4)
我的方法是在指针接收器中传递依赖项(因为处理程序的签名受到限制)并使用接口。每个服务都有相应的接口。对于dynamodb-dynamodbiface。所以在你自己的lambda中 您需要定义一个接收器:
<body>
"stuff & stuff & more stuff"
<script src = "yourSourceFileHereIf_Its_A_SeparateFile.js"></ script>
</body>
将main更改为:
type myReceiver struct {
dynI dynamodbiface.DynamoDBAPI
}
将处理程序更改为
func main() {
sess := session.Must(session.NewSession(&aws.Config{
Region: aws.String("your region")},
))
inj := myReceiver{
dyn: dynamodb.New(sess),
}
lambda.Start(inj.CreateJobCommand)
以及随后对dynamodb API的所有调用都必须通过接口进行:
func (inj *myReceiver) CreateJobCommand(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
然后在测试函数中,您需要模拟响应:
_, err = inj.dynI.PutItem(input)
答案 1 :(得分:1)
尽管这个问题有点老了。我也面临着同样的问题,并在下面的资源中找到了。将其放在这里以造福他人。这些资源展示了如何在golang中编写可口的lambda。
https://ewanvalentine.io/how-im-writing-serverless-services-in-golang-these-days/ 代码-https://github.com/EwanValentine/serverless-api-example
https://dev.to/prozz/serverless-in-go-how-to-write-testable-lambdas-4925 代码-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 代码-https://github.com/jboursiquot/shoutouts
答案 2 :(得分:0)
请检查在docker中运行dynamo-db是否不会帮助您实施测试。
检查:connecting AWS SAM Local with dynamodb in docker
您也可以很容易地将事件传递给测试中的处理程序。
答案 3 :(得分:0)
虽然模拟是一个可行的选择,但您也可以考虑使用专用的AWS帐户进行e2e测试,找到一些示例,包括dynamodb和api网关
答案 4 :(得分:0)
看看LocalStack。它提供了一个易于使用的测试/模拟框架,用于通过在本地计算机或Docker中扩展与AWS兼容的API来开发与AWS相关的应用程序。它支持两打AWS API,其中包括DynamoDB和Lambda。确实是功能测试的绝佳工具,无需为此使用单独的AWS环境。
答案 5 :(得分:0)
这个问题现在有点老了,但是您可以运行dynamodb locally并使用此aws-lambda-go-test模块,该模块可以在本地运行lambda,并且可以用来测试来自lambda的实际响应
我公开并升级了此模块的完整信息