使用*s3.S3对象进行Golang单元测试

huangapple go评论71阅读模式
英文:

Golang unittest with *s3.S3 object

问题

如何对以下代码进行单元测试。我尝试使用counterfiter来伪造输入的"*s3.S3"对象,但对我来说没有起作用。我对counterfiter和Go都不太熟悉,有人可以帮我吗?

func (l *listContentImp) ListS3Content(client *s3.S3) (bool, error) {

  listObj := &s3.ListObjectsV2Input{
    Bucket: aws.String(l.bucket),
  }

  var err error
  l.lObj, err = client.ListObjectsV2(listObj)
  if err != nil {
    return false, err
  }

  return true, nil
}
英文:

How should I unittest following piece of code. I was trying to use coutnerfiter to fake input "*s3.S3" object, but it's not working for me. I am new to coutnerfiter and Go, Can someone please help me on that.

func (l *listContentImp) ListS3Content(client *s3.S3) (bool, error) {

  listObj := &s3.ListObjectsV2Input{
	Bucket: aws.String(l.bucket),
  }

  var err error
  l.lObj, err = client.ListObjectsV2(listObj)
  if err != nil {
	return false, err
  }

  return true, nil
}

答案1

得分: 4

你不应该传递一个对s3.S3结构体的引用。在使用Go v1的AWS SDK时,通常会传递相应服务的接口。对于S3来说,这是s3iface

你的函数签名应该是这样的:

func (l *listContentImp) ListS3Content(client s3iface.S3API) (bool, error)

现在,你可以传递任何实现了s3iface.S3API接口中至少一个方法的结构体。

在运行时,你将传递正确的服务客户端,但在单元测试中,你可以传递一个模拟对象:

type mock struct {
	s3iface.S3API

	output *s3.ListObjectsV2Output
	err     error
}

func (m mock) ListObjectsV2(*s3.ListObjectsV2Input) (*s3.ListObjectsV2Output, error) {
	return m.output, m.err
}

在你的测试中,你创建模拟对象并将其传递给你的函数:

func Test_ListObject(t *testing.T) {
	l := &listContentImp{...}
	m := mock{
		output: &s3.ListObjectsV2Output{...},
		err: nil
	}

	result, err := l.ListS3Content(m)
	
	[...在这里添加检查...]
}
英文:

You shouldn't pass a reference to the s3.S3 struct. When using the AWS SDK for Go v1 you typically pass the services corresponding interface. For S3 this is s3iface.

The signature of your function would look like this:

func (l *listContentImp) ListS3Content(client s3iface.S3API) (bool, error)

Now every struct that you pass that implements at least one of the methods of s3iface.S3API will work.

At runtime you'll pass the proper service client, but in the unit tests you can just pass a mock:

type mock struct {
	s3iface.S3API

	output *s3.ListObjectsV2Output
	err     error
}

func (m mock) ListObjectsV2(*s3.ListObjectsV2Input) (*s3.ListObjectsV2Output, error) {
	return m.output, m.err
}

In your test you create the mock and pass it to your function:

func Test_ListObject(t *testing.T) {
	l := &listContentImp{...}
	m := mock{
		output: &s3.ListObjectsV2Output{...},
		err: nil
	}

	result, err := l.ListS3Content(m)
	
	[... add checks here...]
}

huangapple
  • 本文由 发表于 2022年3月15日 16:18:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/71478975.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定