Golang unittest with *s3.S3 object

Issue

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
}

Solution

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...]
}

Answered By – Jens

Answer Checked By – Timothy Miller (GoLangFix Admin)

Leave a Reply

Your email address will not be published.