I have a function that accepts a path and an S3Client:
ListObjects(folder, s3Client)
I want it to accept a "real" client in production. I.e: s3.New(session.New()
But when I run my tests I'd prefer it to accept my mocked version so that we don't talk to AWS in our tests.
My approach to achieve this is to make an interface that matches both the real S3Client and my mocked version.
Is this the best approach or am I missing anything?
First I have defined the interface with the function I plan to mock.
package core
import "github.com/aws/aws-sdk-go/service/s3"
type MyS3ClientInterface interface {
ListObjects(input *s3.ListObjectsInput) (*s3.ListObjectsOutput, error)
}
GetObjectsFromS3 is implemented like this:
// GetObjectsFromS3 returns a list of objects found in provided path on S3
func GetObjectsFromS3(path string, s3Client core.MyS3ClientInterface) ([]*core.Asset, error) {
// build input variable
result, err := s3Client.ListObjects(input)
// cut..
}
Here's my mocked version of s3Client.ListObjects
package test_awstools
import (
"github.com/aws/aws-sdk-go/service/s3"
)
type MyS3Client struct{}
func (m MyS3Client) ListObjects(input *s3.ListObjectsInput) (*s3.ListObjectsOutput, error) {
output := &s3.ListObjectsOutput{}
return output, nil
}
func (m MyS3Client) GetObject(input *s3.GetObjectInput) (*s3.GetObjectOutput, error) {
// output := &s3.GetObject()
return nil, nil
}
internal/awstools/bucket_test.go
1 package awstools
2
3 import (
4 "fmt"
5 "testing"
6
7 "internal/test_awstools"
8 )
9
10 func TestListObjects(t *testing.T) {
11 folder := "docs"
// Use my mocked version of the S3 client.
12 s3Client := &test_awstools.MyS3Client{}
// And I pass that along to the ListObject function
13 objects, err := ListObjects(folder, s3Client)
14 if err != nil {
15 t.Error(err)
16 }
17 fmt.Println(objects)
18 }