

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Unit Testing dengan AWS SDK untuk Go v2
<a name="unit-testing"></a>

 Saat menggunakan SDK dalam aplikasi Anda, Anda akan ingin mengolok-olok SDK untuk pengujian unit aplikasi Anda. Mengejek SDK memungkinkan pengujian Anda difokuskan pada apa yang ingin Anda uji, bukan internal SDK. 

 Untuk mendukung ejekan, gunakan antarmuka Go alih-alih klien layanan konkret, paginator, dan jenis pelayan, seperti. `s3.Client` Hal ini memungkinkan aplikasi Anda untuk menggunakan pola seperti injeksi dependensi untuk menguji logika aplikasi Anda. 

## Mengejek Operasi Klien
<a name="mocking-client-operations"></a>

 Dalam contoh ini, `S3GetObjectAPI` adalah antarmuka yang mendefinisikan kumpulan operasi Amazon S3 API yang diperlukan oleh `GetObjectFromS3` fungsi. `S3GetObjectAPI`puas dengan metode klien Amazon S3. [GetObject](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#Client.GetObject) 

```
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)
}
```

 Untuk menguji `GetObjectFromS3` fungsi, gunakan `mockGetObjectAPI` untuk memenuhi definisi `S3GetObjectAPI` antarmuka. Kemudian gunakan `mockGetObjectAPI` tipe untuk mengejek output dan respons kesalahan yang dikembalikan dari klien layanan. 

```
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)
            }
        })
    }
}
```

## Mengejek Paginator
<a name="mocking-paginators"></a>

 Mirip dengan klien layanan, paginator dapat diejek dengan mendefinisikan antarmuka Go untuk paginator. Antarmuka itu akan digunakan oleh kode aplikasi Anda. Ini memungkinkan implementasi SDK digunakan saat aplikasi Anda berjalan, dan implementasi tiruan untuk pengujian. 

 Dalam contoh berikut, `ListObjectsV2Pager` adalah antarmuka yang mendefinisikan perilaku untuk Amazon [ListObjectsS3](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#ListObjectsV2Paginator) V2Paginator yang diperlukan oleh fungsi. `CountObjects` 

```
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
}
```

 Untuk menguji`CountObjects`, buat `mockListObjectsV2Pager` tipe untuk memenuhi definisi `ListObjectsV2Pager` antarmuka. Kemudian gunakan `mockListObjectsV2Pager` untuk mereplikasi perilaku paging output dan respons kesalahan dari paginator operasi layanan. 

```
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)
    }
}
```