如何使用 ListObjectsV2Pages s3iface 进行模拟?

问题描述 投票:0回答:1

我正在尝试对一个函数进行单元测试,该函数使用 https://docs.aws.amazon.com/sdk-for-go/api/service/s3/#S3.ListObjectsV2Pages 列出给定 s3 存储桶的内容。

在我的 main.go 文件中,我有这个函数:

func listS3Objects(s3Bucket string, s3Prefix string, svc s3iface.S3API) ([]string, error) {

    input := &s3.ListObjectsV2Input{
        Bucket: aws.String(s3Bucket),
        Prefix: aws.String(s3Prefix),
    }

    var s3Items []string
    err := svc.ListObjectsV2Pages(input, func(resp *s3.ListObjectsV2Output, lastPage bool) bool {
        for _, s3Item := range resp.Contents {
            s3Items = append(s3Items, *s3Item.Key)
        }
        return true
    })

    if err != nil {
        if awsErr, ok := err.(awserr.Error); ok {
            return nil, awsErr
        }
        return nil, err
    }
    return s3Items, nil
}

在我的 main_test.go 文件中,我有:

type mockS3Client struct {
    s3iface.S3API
}

func (m *mockS3Client) ListObjectsV2Pages(input *s3.ListObjectsV2Input, fn func(*s3.ListObjectsV2Output, bool) bool) error {
    var s3Output s3.ListObjectsV2Output
    var s3Object s3.Object
    var s3Objects []*s3.Object
    s3Object.SetKey(*input.Bucket)
    s3Objects = append(s3Objects, &s3Object)
    s3Output.Contents = s3Objects

    fn(&s3Output, true)

    return nil
}

测试如下所示:

func TestListS3Objects(t *testing.T) {
    testBucket := "testBucket"
    testPrefix := "testPrefix"
    var mockSvc mockS3Client
    s3Items, _ := listS3Objects(testBucket, testPrefix, mockSvc.S3API)
    if len(s3Items) != 1 {
        t.Errorf("Expected '%v' elements but got '%v'", 1, len(s3Items))
    }
    if s3Items[0] != testBucket {
        t.Errorf("Expected '%v' value but got '%v'", testBucket, s3Items[0])
    }
}

此测试生成以下堆栈跟踪:

--- FAIL: TestListS3Objects (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
    panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x5a0 pc=0x797066]

goroutine 7 [running]:
testing.tRunner.func1(0xc00017e300)
    /usr/local/go/src/testing/testing.go:874 +0x3a3
panic(0x800c20, 0xc657c0)
    /usr/local/go/src/runtime/panic.go:679 +0x1b2
github.com/AirHelp/business-metrics-restore.listS3Objects(0x88d6aa, 0xa, 0x88d6b4, 0xa, 0x0, 0x0, 0x1, 0xc000018dd8, 0x44f278, 0x5aa38b1b10f7, ...)
    /workspaces/business-metrics-restore/bmr.go:189 +0x126
github.com/AirHelp/business-metrics-restore.TestListS3Objects(0xc00017e300)
    /workspaces/business-metrics-restore/bmr_test.go:59 +0x65
testing.tRunner(0xc00017e300, 0x8a7fa8)
    /usr/local/go/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
    /usr/local/go/src/testing/testing.go:960 +0x350
FAIL    github.com/AirHelp/business-metrics-restore 0.044s
FAIL
Error: Tests failed.

我的印象是我的 ListObjectsV2Pages 的模拟版本可能存在一些问题,但无法找到根本原因。我试图让这个模拟函数尽可能简单......

有人可以帮助我吗?

谢谢!

最诚挚的问候, 拉法尔。

unit-testing go amazon-s3
1个回答
0
投票

我是如何做到的,我将 s3iface.S3API 嵌入到我的应用程序代码中的一个新结构中,并添加了一个切片来保存 s3items,然后提供了一个单独的分页器功能

type myS3 struct {
    s3iface.S3API
    s3items     []*s3Item.Key
}

func (s *myS3) findObjects(bucket, prefix string) error {
    err := s.ListObjectsV2Pages(&s3.ListObjectsV2Input{
        Bucket: &bucket,
        Prefix: &prefix,
    }, s.Paginator)
    return err
}

func (s *myS3) paginator(page *s3.ListObjectsV2Output, lastPage bool) bool {
    for _, content := range page.Contents {
        s.s3items = append(s.s3items, *content.Key)
    }
    return lastPage
}

这样,您只需要测试分页器是否正确填充 s3items 字段,并查看调用 findObjects 的任何函数是否正确处理错误

© www.soinside.com 2019 - 2024. All rights reserved.