Как мне выполнить юнит-тестирование aws-sdk-go-v2 - PullRequest
0 голосов
/ 16 мая 2018

Я все еще использую go-интерфейсы и могу смутить функцию WaitUntilTableExists . Но не может издеваться PutItemRequest .

Вот мой main.go фрагмент

func MyPutItem(d mydata, client dynamodbiface.DynamoDBAPI) error {
    input := &dynamodb.PutItemInput{
        ....
    }
    req := client.PutItemRequest(input)
    result, err := req.Send()
    log.Println(result)
    return err
}

main_test.go фрагмент

type mockDynamoDBClient struct {
    dynamodbiface.DynamoDBAPI
}

func (m *mockDynamoDBClient) PutItemRequest(input *dynamodb.PutItemInput) dynamodb.PutItemRequest {
    // Most probably this is where I need your help
}

func TestStoreInDynamoDB(t *testing.T) {
    var mockClient = new(mockDynamoDBClient)
    d := mydata{}
    result := DynampDBPutItem(d, mockClient)
    t.Log(result)
}

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Подделка SDK так работает:

main_test.go

type fakeDynamoDBClient struct {
    dynamodbiface.DynamoDBAPI
}

func (m *fakeDynamoDBClient) GetItemRequest(input *dynamodb.GetItemInput) dynamodb.GetItemRequest {
    return dynamodb.GetItemRequest{
        Request: &aws.Request{
            Data: &dynamodb.GetItemOutput{
                Item: map[string]dynamodb.AttributeValue{
                    "count": dynamodb.AttributeValue{
                        N: aws.String("10"),
                    },
                },
            },
        },
    }
}

func (m *fakeDynamoDBClient) PutItemRequest(input *dynamodb.PutItemInput) dynamodb.PutItemRequest {
    return dynamodb.PutItemRequest{
        Request: &aws.Request{
            Data: &dynamodb.PutItemOutput{},
        },
    }
}

func TestUpdateCount(t *testing.T) {
    err := UpdateCount(10, &fakeDynamoDBClient{})
    if err != nil {
        t.Error("Failed to update badge count on dynamodb", err)
    }
}

main.go

func UpdateCount(count int, client dynamodbiface.DynamoDBAPI) error {
    ...
}
0 голосов
/ 16 мая 2018

Используя ваш пример, вы можете сделать свои утверждения прямо в макете

type mockDynamoDBClient struct {
    t *testing.T
    expected *dynamodb.PutItemInput
    response *dynamodb.PutItemOutput
    dynamodbiface.DynamoDBAPI
}

func (m *mockDynamoDBClient) PutItemRequest(input *dynamodb.PutItemInput) dynamodb.PutItemOutput {
    // some kind of equality check
    if !reflect.DeepEqual(m.expected, input) {
        t.Errorf(...// some error message)
    }
    return m.response
}

Основные проблемы с этим примером:

t *testing.T, expected *dynamodb.PutItemInput и ответ response *dynamodb.PutItemOutput все должно быть внутри структуры, которая выглядит грязной.

Вместо этого вы можете использовать анонимную функцию, чтобы сделать это:

type mockDynamoDBClient struct {
    f func(input *dynmaodb.PutItemInput) *dynamodb.PutItemOutput
    dynamodbiface.DynamoDBAPI
}

func (m *mockDynamoDBClient) PutItemRequest(input *dynamodb.PutItemInput) dynamodb.PutItemOutput {
    return m.f(input)
}

Теперь в тестовом коде вы можете немного лучше использоватьструктура макета:

m := &mockDynamoDBClient{
    f: func(input *dynamodb.PutItemInput) *dynamodb.PutItemOutput {
        // assertions on input
        // return mock responses
    }
}

РЕДАКТИРОВАТЬ на основе комментария:

Вам также следует рассмотреть вопрос о том, чтобы сделать вашу функцию MyPutItem зависимой от наименьшего возможного интерфейса.Если вам нужен только доступ к методу PutItemRequest, вы можете создать свой собственный интерфейс для этого метода и использовать его в MyPutItem

type MyDynamoPutter interface {
    func (c *DynamoDB) PutItemRequest(input *PutItemInput) PutItemRequest
}

Затем в MyPutItem вы можете использовать свой собственный интерфейс:

func MyPutItem(d mydata, client MyDynamoPutter) error {
    input := &dynamodb.PutItemInput{
        ....
    }
    req := client.PutItemRequest(input)
    result, err := req.Send()
    log.Println(result)
    return err
}

Это уменьшает площадь поверхности, которая вам нужна для макета!

...