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

如何在 golang 中模拟 request.Request

如何在 golang 中模拟 request.Request

Go
catspeake 2023-06-01 17:22:39
我正在使用github.com/aws/aws-sdk-go/aws/request获取预签名 URL,我需要将文件上传到 AWS 中的 s3 存储桶。我目前正在编写测试,为此我需要模拟func (r *Request) Presign(expire time.Duration). request.Request是一个结构,而不是一个接口,所以我不知道,我怎么能模拟它。
查看完整描述

3 回答

?
精慕HU

TA贡献1845条经验 获得超8个赞

这不是直接回答你的问题,但它可能会完全消除问题的基础。


Go 中的一个巧妙之处在于,您可以使用接口轻松地隔离依赖项。如果您的代码,即您需要测试的部分,正在Presign间接使用,那么测试就很简单了。


即创建一个界面


type HigherLevelAws interface {

    Upload(file string) error

}

并在您的代码中使用此接口以及Upload. 然后您可以使用例如https://godoc.org/github.com/stretchr/testify/mock轻松模拟它


实际的实现看起来像这样


type ActualAwsImpl struct {

    aws *aws.Client

}


func (a *ActualAwsImpl) Upload(file string) error {

    aws.Presign...

}

这允许您测试代码的业务部分,但当然,仍然会在ActualAwsImpl. 然而,这些未经测试的代码可以通过 aws sdk 本身的单元和集成测试来保证工作。无论哪种方式,在我的组织中,我们使用在 docker 中运行的假 aws 服务(例如https://github.com/gliffy/fake-s3)对此进行测试。


查看完整回答
反对 回复 2023-06-01
?
MMTTMM

TA贡献1869条经验 获得超4个赞

我不得不模拟 S3 命令的请求。代码如下:


req, result := r.s3.ListObjectsV2Request(&s3.ListObjectsV2Input{

        Bucket: aws.String(configs.Settings.S3Bucket),

    })


    err := req.Send()

Mock 函数必须返回一个请求对象


func (m *mockS3ProviderClient) ListObjectsV2Request(input *s3.ListObjectsV2Input) (req *request.Request, output *s3.ListObjectsV2Output) {


    err := input.Validate()

    req = &request.Request{

        HTTPRequest: &http.Request{},

        Error:       err,

    }


    output = &s3.ListObjectsV2Output{

        Contents: []*s3.Object{

            {Key:aws.String("File1")},

            {Key:aws.String("File2")},

        },

    }


    return req, output

}


查看完整回答
反对 回复 2023-06-01
?
慕容708150

TA贡献1831条经验 获得超4个赞

您可以直接为该函数创建一个接口,如下所示:


type presigner interface {

    Presign(expire time.Duration) (string, error)

}

如果您在一个单独的函数中实现您的逻辑,该函数将 apresigner作为参数,如下所示(称为依赖注入):


func Upload(p presigner, files string) error {

    // ...

    res, err := p.Presign(someduration)

    if err != nil {

        return err

    }

    // and so on

}

然后很容易在你的测试中模拟 - 只需实现presigner接口并让Presign函数返回你所期望的:


type presignerMock struct {}


func (p *presignerMock) Presign(d time.Duration) (string, error) {

    return "yay", nil

}

要测试不同的场景,您可以向 中添加字段presignerMock并在您的实现中返回它们:


type presignerMock {

    res string

    err error

}


func (p *presignerMock) Presign(d time.Duration) (string, error) {

    return p.res, p.err

}


查看完整回答
反对 回复 2023-06-01
  • 3 回答
  • 0 关注
  • 155 浏览
慕课专栏
更多

添加回答

举报

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