Go AWS SDK v2中如何mock DynamoDB的多个GetItem请求?
Go AWS SDK v2 多DynamoDB Get调用Mock实现方案
可以实现,不需要依赖额外工具,修改自定义mock逻辑即可适配多GetItem调用场景,两种常用实现方案如下:
方案1:按调用顺序返回结果
适合调用顺序固定的测试场景,核心逻辑是给mock结构体增加返回值队列和调用计数器,每次调用按顺序返回队列中的对应值。
第一步:修改mock结构体定义
import ( "context" "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" ) type mockDynamoDB struct { // 按调用顺序存储所有GetItem的返回值 GetItemResponses []struct { Output dynamodb.GetItemOutput Error error } callIndex int // 记录当前是第几次调用 }
第二步:实现GetItem接口方法
需要和AWS SDK v2的DynamoDB Client的GetItem方法签名完全一致:
func (m *mockDynamoDB) GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error) { if m.callIndex >= len(m.GetItemResponses) { panic("测试出现未预设的额外GetItem调用") } resp := m.GetItemResponses[m.callIndex] m.callIndex++ return &resp.Output, resp.Error }
第三步:测试中注入多返回值
按业务调用顺序传入预设结果,第一次调用对应GetEventStore的返回,第二次对应GetConfig的返回:
// 预设测试数据 eventDetails := map[string]types.AttributeValue{ "id": &types.AttributeValueMemberS{Value: "test_id"}, "status": &types.AttributeValueMemberS{Value: "completed"}, } config := map[string]types.AttributeValue{ "key": &types.AttributeValueMemberS{Value: "test_config_key"}, "value": &types.AttributeValueMemberS{Value: "test_config_value"}, } // 初始化mock client DB := client.DynamoDBClient{ Client: &mockDynamoDB{ GetItemResponses: []struct { Output dynamodb.GetItemOutput Error error }{ // 第一次GetItem调用(GetEventStore)返回值 { Output: dynamodb.GetItemOutput{Item: eventDetails}, Error: nil, }, // 第二次GetItem调用(GetConfig)返回值 { Output: dynamodb.GetItemOutput{Item: config}, Error: nil, }, }, }, }
方案2:按请求参数匹配返回结果
适合调用顺序不固定、需要校验请求合法性的场景,核心逻辑是在mock的GetItem方法中判断传入的请求参数(如表名、主键值),匹配到对应的业务查询后返回预设结果,还可以自动校验请求是否符合预期。
示例实现:
type mockDynamoDB struct { EventDetails map[string]types.AttributeValue Config map[string]types.AttributeValue TestEventId string TestConfigKey string } func (m *mockDynamoDB) GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error) { tableName := *params.TableName // 匹配事件存储表的查询 if tableName == "event_store" { reqId := params.Key["id"].(*types.AttributeValueMemberS).Value if reqId != m.TestEventId { panic(fmt.Sprintf("期望查询事件ID %s,实际查询ID %s", m.TestEventId, reqId)) } return &dynamodb.GetItemOutput{Item: m.EventDetails}, nil } // 匹配配置存储表的查询 if tableName == "config_store" { reqKey := params.Key["key"].(*types.AttributeValueMemberS).Value if reqKey != m.TestConfigKey { panic(fmt.Sprintf("期望查询配置键 %s,实际查询键 %s", m.TestConfigKey, reqKey)) } return &dynamodb.GetItemOutput{Item: m.Config}, nil } panic(fmt.Sprintf("未预设的表查询:%s", tableName)) }
测试使用示例:
DB := client.DynamoDBClient{ Client: &mockDynamoDB{ EventDetails: eventDetails, Config: config, TestEventId: "test_id", TestConfigKey: "test_config_key", }, }
如果需要覆盖错误场景,只需要在对应返回位置把Error字段设置为自定义错误即可,无需修改其他逻辑。
内容的提问来源于stack exchange,提问作者user17090811
相关产品推荐
相关产品推荐

