Teste de unidade com o AWS SDK para Go v2 - AWS SDK para Go v2

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Teste de unidade com o AWS SDK para Go v2

Ao usar o SDK em sua aplicação, simule o SDK no teste de unidade da aplicação. A simulação do SDK permite que o teste se concentre no que você realmente quer testar, não nos componentes internos do SDK.

Para oferecer suporte à simulação, use interfaces de Go em vez de tipos concretos de cliente de serviço, paginadores e waiter, como s3.Client. Isso permite que a aplicação use padrões como injeção de dependência para testar a lógica da aplicação.

Como simular operações de cliente

Neste exemplo, S3GetObjectAPI é uma interface que define o conjunto de operações de API do Amazon S3 exigidas pela função GetObjectFromS3. S3GetObjectAPI é satisfeita pelo método GetObject do cliente do Amazon S3.

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

Para testar a função GetObjectFromS3, use a mockGetObjectAPI para satisfazer a definição da interface S3GetObjectAPI. Depois, use o tipo mockGetObjectAPI para simular a saída e as respostas de erro retornadas pelo cliente do serviço.

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

Simulação de paginadores

Semelhante aos clientes de serviço, os paginadores podem ser simulados definindo uma interface de Go para o paginador. Essa interface seria usada pelo código da aplicação. Isso permite que a implementação do SDK seja usada quando a aplicação está em execução e uma implementação simulada seja usada nos testes.

No exemplo a seguir, ListObjectsV2Pager é uma interface que define os comportamentos necessários do ListObjectsV2Paginator do Amazon S3 para a função 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 }

Para testar CountObjects, crie o tipo mockListObjectsV2Pager para satisfazer a definição da interface ListObjectsV2Pager. Depois, use mockListObjectsV2Pager para replicar o comportamento de paginação das respostas de saída e erro do paginador da operação do serviço.

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