我如何单元测试aws-sdk-go-v2 dynamodb implimentation

时间:2018-05-16 18:21:35

标签: amazon-web-services go aws-sdk aws-sdk-go

我仍然抓住go-interfaces,我可以嘲笑WaitUntilTableExists func。但无法模仿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 :(得分:2)

举个例子,你可以直接在模拟

中做断言
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.Texpected *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
}

这减少了你需要模拟的表面积!

答案 1 :(得分:1)

假冒这样的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 {
    ...
}