为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
天涯尽头无女友 2022-08-01 10:37:21
我试图有史以来第一次编写一些单元测试,并且我正在使用golang为一个利用aws lambda的副项目做这件事。下面是两个文件。main.go获取包含电子邮件地址的事件,并在认知用户池中创建用户。main_test.go应该模拟 中的函数,但是当我尝试运行测试时,我遇到了错误。createUsermain.go在观看此YouTube视频后,我刚刚将我的代码从全局实例化客户端切换到在awsd工具包接口上使用指针接收器方法。main.gopackage mainimport (    "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),            },        },    }  
查看完整描述

1 回答

?
aluckdog

TA贡献1847条经验 获得超7个赞

我认为这里的问题是,你想嘲笑方法,但实际上确实嘲笑了方法。AdminCreateUser()CreateUser()


因此,当您创建结构的新实例(“实现”接口,然后在其上调用方法)时,它不会实现并且失败。mockCreateUsercidpif.CognitoIdentityProviderAPIAdminCreateUser()


您的相关代码应该是这样的:main_test.go


type 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 的简化版本。显然,命名等取决于您。还有很多错误处理缺失等。


我认为最大的优点是,您可以通过.如果您想为每个测试和不同的行为使用不同的电子邮件等,只需更改配置即可。configapplication


main.go


package main


import (

    "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.go


package main


import (

    "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")

        }

    })

}


查看完整回答
反对 回复 2022-08-01
  • 1 回答
  • 0 关注
  • 93 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信