猿问

AWS 开发工具包 Go Lambda 单元测试

我试图有史以来第一次编写一些单元测试,并且我正在使用golang为一个利用aws lambda的副项目做这件事。

下面是两个文件。

main.go获取包含电子邮件地址的事件,并在认知用户池中创建用户。

main_test.go应该模拟 中的函数,但是当我尝试运行测试时,我遇到了错误。createUsermain.go

在观看此YouTube视频后,我刚刚将我的代码从全局实例化客户端切换到在awsd工具包接口上使用指针接收器方法。

main.go

package main


import (

    "fmt"

    "log"

    "os"


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

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

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

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

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

    cidp "github.com/aws/aws-sdk-go/service/cognitoidentityprovider"

    cidpif "github.com/aws/aws-sdk-go/service/cognitoidentityprovider/cognitoidentityprovideriface"

    lib "github.com/sean/repo/lib"

)


type createUserEvent struct {

    EmailAddress string `json:"email_address"`

}


type awsService struct {

    cidpif.CognitoIdentityProviderAPI

}


func (c *awsService) createUser(e createUserEvent) error {

    input := &cidp.AdminCreateUserInput{

        UserPoolId:             aws.String(os.Getenv("USER_POOL_ID")),

        Username:               aws.String(e.EmailAddress),

        DesiredDeliveryMediums: []*string{aws.String("EMAIL")},

        ForceAliasCreation:     aws.Bool(true),

        UserAttributes: []*cidp.AttributeType{

            {

                Name:  aws.String("email"),

                Value: aws.String(e.EmailAddress),

            },

        },

    }

  

天涯尽头无女友
浏览 94回答 1
1回答

aluckdog

我认为这里的问题是,你想嘲笑方法,但实际上确实嘲笑了方法。AdminCreateUser()CreateUser()因此,当您创建结构的新实例(“实现”接口,然后在其上调用方法)时,它不会实现并且失败。mockCreateUsercidpif.CognitoIdentityProviderAPIAdminCreateUser()您的相关代码应该是这样的:main_test.gotype mockCreateUser struct {    cidpif.CognitoIdentityProviderAPI    Response cidp.AdminCreateUserOutput}func (d mockCreateUser) CreateUser(e createUserEvent) error {    return nil}添加以下“虚拟”(并删除该方法)应该就足够了:CreateUser()func (d mockCreateUser) AdminCreateUser(*cidp.AdminCreateUserInput) (*cidp.AdminCreateUserOutput, error) {    return d.Response, nil}此外,我想提出一种略有不同的方法来对您的 Lambda 进行单元测试。你的代码在可测试性方面已经相当不错了。但你可以做得更好。我建议创建一个“应用程序”,其行为类似于您的结构,但不实现任何AWS接口。相反,它包含一个结构。此配置包含您从环境中读取的值 (例如 , ) 以及 AWS 服务的实例。awsServiceconfigurationUSER_POOL_IDEMAIL我们的想法是,您的所有方法和函数都使用此配置,从而允许您在单元测试期间使用模拟 AWS 服务,并在运行时使用“适当”的服务实例。以下是 Lambda 的简化版本。显然,命名等取决于您。还有很多错误处理缺失等。我认为最大的优点是,您可以通过.如果您想为每个测试和不同的行为使用不同的电子邮件等,只需更改配置即可。configapplicationmain.gopackage mainimport (    "os"    "github.com/aws/aws-lambda-go/events"    "github.com/aws/aws-lambda-go/lambda"    "github.com/aws/aws-sdk-go/aws"    "github.com/aws/aws-sdk-go/aws/session"    "github.com/aws/aws-sdk-go/service/cognitoidentityprovider"    "github.com/aws/aws-sdk-go/service/cognitoidentityprovider/cognitoidentityprovideriface")type createUserEvent struct {    EmailAddress string `json:"email_address"`}type configuration struct {    poolId string    idp    cognitoidentityprovideriface.CognitoIdentityProviderAPI}type application struct {    config configuration}func (app *application) createUser(event createUserEvent) error {    input := &cognitoidentityprovider.AdminCreateUserInput{        UserPoolId:             aws.String(app.config.poolId),        Username:               aws.String(event.EmailAddress),        DesiredDeliveryMediums: aws.StringSlice([]string{"EMAIL"}),        ForceAliasCreation:     aws.Bool(true),        UserAttributes: []*cognitoidentityprovider.AttributeType{            {                Name:  aws.String("email"),                Value: aws.String(event.EmailAddress),            },        },    }    _, err := app.config.idp.AdminCreateUser(input)    if err != nil {        return err    }    return nil}func (app *application) handler(event createUserEvent) (events.APIGatewayProxyResponse, error) {    err := app.createUser(event)    if err != nil {        return events.APIGatewayProxyResponse{}, err    }    return events.APIGatewayProxyResponse{}, nil}func main() {    config := configuration{        poolId: os.Getenv("USER_POOL_ID"),        idp:    cognitoidentityprovider.New(session.Must(session.NewSession())),    }    app := application{config: config}    lambda.Start(app.handler)}main_test.gopackage mainimport (    "testing"    "github.com/aws/aws-sdk-go/service/cognitoidentityprovider"    "github.com/aws/aws-sdk-go/service/cognitoidentityprovider/cognitoidentityprovideriface")type mockAdminCreateUser struct {    cognitoidentityprovideriface.CognitoIdentityProviderAPI    Response *cognitoidentityprovider.AdminCreateUserOutput    Error    error}func (d mockAdminCreateUser) AdminCreateUser(*cognitoidentityprovider.AdminCreateUserInput) (*cognitoidentityprovider.AdminCreateUserOutput, error) {    return d.Response, d.Error}func TestCreateUser(t *testing.T) {    t.Run("Successfully create user", func(t *testing.T) {        idpMock := mockAdminCreateUser{            Response: &cognitoidentityprovider.AdminCreateUserOutput{},            Error:    nil,        }        app := application{config: configuration{            poolId: "test",            idp:    idpMock,        }}        err := app.createUser(createUserEvent{EmailAddress: "user@example.com"})        if err != nil {            t.Fatal("User should have been created")        }    })}
随时随地看视频慕课网APP

相关分类

Go
我要回答