首页 > 解决方案 > How do I write unit test aws-sdk-go-v2 dynamodb implementation

问题描述

I am still grasping go-interfaces and I can mock the WaitUntilTableExists func. But unable to mock PutItemRequest.

Here's my main.go snippet

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 snippet

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

标签: amazon-web-servicesgoaws-sdkaws-sdk-go

解决方案


以您为例,您可以直接在模拟中进行断言

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
}

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


推荐阅读