# Source: https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/unit-testing.html

[](/pdfs/sdk-for-go/v2/developer-guide/aws-sdk-go-v2-dg.pdf#unit-testing "Open PDF")

[Documentation](/index.html)[AWS SDK for Go v2](/sdk-for-go/index.html)[Developer Guide](welcome.html)

Mocking Client OperationsMocking Paginators

# Unit Testing with the AWS SDK for Go v2

When using the SDK in your application, you'll want to mock out the SDK for your application's unit test. Mocking out the SDK allows your test to be focused on what you want to test, not the internals of the SDK. 

To support mocking, use Go interfaces instead of concrete service client, paginators, and waiter types, such as `s3.Client`. This allows your application to use patterns like dependency injection to test your application logic. 

## Mocking Client Operations

In this example, `S3GetObjectAPI` is an interface that defines the set of Amazon S3 API operations required by the `GetObjectFromS3` function. `S3GetObjectAPI` is satisfied by the Amazon S3 client's [GetObject](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#Client.GetObject) method. 
    
    
    import "context"
    import "github.com/aws/aws-sdk-go-v2/service/s3"
    
    // ...
    
    type S3GetObjectAPI interface {
        GetObject(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error)
    }
    
    func GetObjectFromS3(ctx context.Context, api S3GetObjectAPI, bucket, key string) ([]byte, error) {
        object, err := api.GetObject(ctx, &s3.GetObjectInput{
            Bucket: &bucket,
            Key:    &key,
        })
        if err != nil {
            return nil, err
        }
        defer object.Body.Close()
    
        return ioutil.ReadAll(object.Body)
    }
    

To test the `GetObjectFromS3` function, use the `mockGetObjectAPI` to satisfy the `S3GetObjectAPI` interface definition. Then use the `mockGetObjectAPI` type to mock output and error responses returned from the service client. 
    
    
    import "testing"
    import "github.com/aws/aws-sdk-go-v2/service/s3"
    
    // ...
    
    type mockGetObjectAPI func(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error)
    
    func (m mockGetObjectAPI) GetObject(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error) {
        return m(ctx, params, optFns...)
    }
    
    func TestGetObjectFromS3(t *testing.T) {
        cases := []struct {
            client func(t *testing.T) S3GetObjectAPI
            bucket string
            key string
            expect []byte
        }{
            {
                client: func(t *testing.T) S3GetObjectAPI {
                    return mockGetObjectAPI(func(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error) {
                        t.Helper()
                        if params.Bucket == nil {
                            t.Fatal("expect bucket to not be nil")
                        }
                        if e, a := "fooBucket", *params.Bucket; e != a {
                            t.Errorf("expect %v, got %v", e, a)
                        }
                        if params.Key == nil {
                            t.Fatal("expect key to not be nil")
                        }
                        if e, a := "barKey", *params.Key; e != a {
                            t.Errorf("expect %v, got %v", e, a)
                        }
    
                        return &s3.GetObjectOutput{
                            Body: ioutil.NopCloser(bytes.NewReader([]byte("this is the body foo bar baz"))),
                        }, nil
                    })
                },
                bucket: "amzn-s3-demo-bucket>",
                key:    "barKey",
                expect: []byte("this is the body foo bar baz"),
            },
        }
    
        for i, tt := range cases {
            t.Run(strconv.Itoa(i), func(t *testing.T) {
                ctx := context.TODO()
                content, err := GetObjectFromS3(ctx, tt.client(t), tt.bucket, tt.key)
                if err != nil {
                    t.Fatalf("expect no error, got %v", err)
                }
                if e, a := tt.expect, content; bytes.Compare(e, a) != 0 {
                    t.Errorf("expect %v, got %v", e, a)
                }
            })
        }
    }
    

## Mocking Paginators

Similar to service clients, paginators can be mocked by defining a Go interface for the paginator. That interface would be used by your application's code. This allows the SDK's implementation to be used when your application is running, and a mocked implementation for testing. 

In the following example, `ListObjectsV2Pager` is an interface that defines the behaviors for the Amazon S3 [ListObjectsV2Paginator](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#ListObjectsV2Paginator) required by `CountObjects` function. 
    
    
    import "context"
    import "github.com/aws/aws-sdk-go-v2/service/s3"
    
    // ...
    
    type ListObjectsV2Pager interface {
        HasMorePages() bool
        NextPage(context.Context, ...func(*s3.Options)) (*s3.ListObjectsV2Output, error)
    }
    
    func CountObjects(ctx context.Context, pager ListObjectsV2Pager) (count int, err error) {
        for pager.HasMorePages() {
            var output *s3.ListObjectsV2Output
            output, err = pager.NextPage(ctx)
            if err != nil {
                return count, err
            }
            count += int(output.KeyCount)
        }
        return count, nil
    }
    

To test `CountObjects`, create the `mockListObjectsV2Pager` type to satisfy the `ListObjectsV2Pager` interface definition. Then use `mockListObjectsV2Pager` to replicate the paging behavior of output and error responses from the service operation paginator. 
    
    
    import "context"
    import  "fmt"
    import "testing"
    import "github.com/aws/aws-sdk-go-v2/service/s3"
    
    // ...
    
    type mockListObjectsV2Pager struct {
        PageNum int
        Pages   []*s3.ListObjectsV2Output
    }
    
    func (m *mockListObjectsV2Pager) HasMorePages() bool {
        return m.PageNum < len(m.Pages)
    }
    
    func (m *mockListObjectsV2Pager) NextPage(ctx context.Context, f ...func(*s3.Options)) (output *s3.ListObjectsV2Output, err error) {
        if m.PageNum >= len(m.Pages) {
            return nil, fmt.Errorf("no more pages")
        }
        output = m.Pages[m.PageNum]
        m.PageNum++
        return output, nil
    }
    
    func TestCountObjects(t *testing.T) {
        pager := &mockListObjectsV2Pager{
            Pages: []*s3.ListObjectsV2Output{
                {
                    KeyCount: 5,
                },
                {
                    KeyCount: 10,
                },
                {
                    KeyCount: 15,
                },
            },
        }
        objects, err := CountObjects(context.TODO(), pager)
        if err != nil {
            t.Fatalf("expect no error, got %v", err)
        }
        if expect, actual := 30, objects; expect != actual {
            t.Errorf("expect %v, got %v", expect, actual)
        }
    }
    

![Warning](https://d1ge0kk1l5kms0.cloudfront.net/images/G/01/webservices/console/warning.png) **Javascript is disabled or is unavailable in your browser.**

To use the Amazon Web Services Documentation, Javascript must be enabled. Please refer to your browser's Help pages for instructions.

[Document Conventions](/general/latest/gr/docconventions.html)

Timing SDK operations

Code examples

Did this page help you? - Yes

Thanks for letting us know we're doing a good job!

If you've got a moment, please tell us what we did right so we can do more of it.

Did this page help you? - No

Thanks for letting us know this page needs work. We're sorry we let you down.

If you've got a moment, please tell us how we can make the documentation better.