在Golang中模拟外部依赖项

时间:2018-08-11 11:18:20

标签: unit-testing go

我正在使用一个程序来连接到AWS S3并获取文件。 我想为此编写一些测试,但更普遍的是,我想知道如何在Golang中进行这些模拟。我知道有一些库可以创建模拟,但是如果我没记错的话,我读到有人建议仅将标准库用于单元测试是最好的方法。

那么,您将如何测试这样的功能?

func (s S3Input) Sample(key string) ([]byte, error) {
    var buf []byte
    waBuf := aws.NewWriteAtBuffer(buf)

    _, err := s.Downloader.Download(
        waBuf,
        &s3.GetObjectInput{
            Bucket: aws.String(s.Bucket),
            Key:    aws.String(key),
        },
    )
    if err != nil {
        return nil, err
    }

    return buf, nil
}

谢谢!

1 个答案:

答案 0 :(得分:3)

一种方法是将依赖项注入到您的结构中,例如:

type S3Inputer interface {
    NewWriteAtBuffer(buf []byte) *aws.WriteAtBuffer
    String(v string) *string
}

type S3Input struct {
    newWriteAtBufferFunc func(buf []byte) *aws.WriteAtBuffer
    stringFunc           func(v string) *string
}

func (s *S3Input) NewWriteAtBuffer(buf []byte) *WriteAtBuffer {
    return s.newWriteAtBufferFunc(buf)
}

func (s *S3Input) String(v string) *string {
    return s.stringFunc(v)
}

func (s S3Input) Sample(key string) ([]byte, error) {
    var buf []byte
    waBuf := s.NewWriteAtBuffer(buf)

    _, err := s.Downloader.Download(
        waBuf,
        &s3.GetObjectInput{
            Bucket: s.String(s.Bucket),
            Key:    s.String(key),
        },
    )
    if err != nil {
        return nil, err
    }

    return buf, nil
}

func main() {
    s := &S3Input{
        StringFunc:           aws.String,
        NewWriteAtBufferFunc: aws.NewWriteAtBuffer,
    }

    // ...
}

这使您可以用所需的任何测试替换那些功能,而无需任何测试框架。

然后,测试功能将如下所示:

func (s S3Input) TestSample(t *testing.T) {
    s3Mock := &S3Input{
        StringFunc:           (func (v string) *string {
            return nil
        }),
        NewWriteAtBufferFunc: (func (buf []byte) *aws.WriteAtBuffer {
            return nil
        }),
    }

    res, err := s3Mock.Sample(...) //
    // asserts & error checks
}

您可以通过创建S3InputMock类型而不是重用基础类型来改进它,两者都将实现S3Inputer接口,并且您的模拟对象可以具有允许它帮助您进行测试的属性。例如,它可以计算调用函数的次数,存储接收到的参数,使方法的行为取决于您设置的属性(以便于测试)等。