如何在流程中模拟多个 AWS DynamoDB 的 GetItem() 请求?

huangapple go评论95阅读模式
英文:

How to mock AWS DynamoDB if multiple GetItem() in flow?

问题

eventHandler.go

func eventHandler(Id) error {
	eventDetails, err := GetEventStore(svc.Connection.DynamoDBClient, Id)
	if err != nil {
		log.Error("Error while reading Store", err)
		return err
	}
	if eventDetails.status == "completed" {
		config, err := GetConfig(svc.Connection.DynamoDBClient, Key)
		if err != nil {
			log.Error("Error while reading Config Store", err)
			return err
		}
        // process it
    }
  return nil
}

大部分数据都存储在存储中,所以在为eventHandler编写单元测试时,如何使用多个GetItemOutput来模拟DynamoDB?

eventHnadler_test.go

...
eventDetails := {
 //data
}
config := {
//data
}
		DB := client.DynamoDBClient{
			Client: mockDynamoDB{
				Output: dynamodb.GetItemOutput{
					Item: eventDetails,
				},
				Error: tc.Error,
			},
		}
...

在Go的AWS SDK v2中,可以模拟多个get调用吗?

英文:

eventHandler.go

func eventHandler(Id) error {
	eventDetails, err := GetEventStore(svc.Connection.DynamoDBClient, Id)
	if err != nil {
		log.Error("Error while reading Store", err)
		return err
	}
	if eventDetails.status == "completed" {
		config, err := GetConfig(svc.Connection.DynamoDBClient, Key)
		if err != nil {
			log.Error("Error while reading Config Store", err)
			return err
		}
        // process it
    }
  return nil
}

Most of our data is stored in stores so while writing unit tests for eventHandler how to mockDynamoDB with multiple GetItemOutput ?

eventHnadler_test.go

...
eventDetails := {
 //data
}
config := {
//data
}
		DB := client.DynamoDBClient{
			Client: mockDynamoDB{
				Output: dynamodb.GetItemOutput{
					Item: eventDetails,
				},
				Error: tc.Error,
			},
		}
...

Can multiple get calls be mocked in GO aws sdk v2?

答案1

得分: 1

因为AWS DynamoDB进行了重构,所以github.com/aws/aws-sdk-go-v2/service/dynamodb/dynamodbiface不再存在,你需要实现自己的接口来正确模拟DynamoDB。

你的AWS实现的包装器应该类似于以下代码:

type Dynamodb struct {
    Client DynamoAPI
}

type DynamoAPI interface {
    GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error)
    UpdateItem(ctx context.Context, params *dynamodb.UpdateItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.UpdateItemOutput, error)
    PutItem(ctx context.Context, params *dynamodb.PutItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error)
    DeleteItem(ctx context.Context, params *dynamodb.DeleteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.DeleteItemOutput, error)
    Query(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error)
    Scan(ctx context.Context, params *dynamodb.ScanInput, optFns ...func(*dynamodb.Options)) (*dynamodb.ScanOutput, error)
}

以下是可能的模拟实现:

type mockDynamodb struct {
    rbaws.DynamoAPI
    *dynamodb.Client
    clientError error
}

func (m mockDynamodb) GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error) {
    return &dynamodb.GetItemOutput{
        Item: map[string]types.AttributeValue{},
    }, m.clientError
}

请注意,这只是一个示例,你可能需要根据你的具体需求进行适当的修改。

英文:

Because AWS dynamo DB got restructured so

github.com/aws/aws-sdk-go-v2/service/dynamodb/dynamodbiface doesn't exists anymore you have to implement your own interface to have proper dynamo mocking

your Wrapper around aws implentation should be something similar like that

type Dynamodb struct {
	Client  DynamoAPI
}

type DynamoAPI interface {
    	GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error)
    	UpdateItem(ctx context.Context, params *dynamodb.UpdateItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.UpdateItemOutput, error)
    	PutItem(ctx context.Context, params *dynamodb.PutItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error)
    	DeleteItem(ctx context.Context, params *dynamodb.DeleteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.DeleteItemOutput, error)
    	Query(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error)
    	Scan(ctx context.Context, params *dynamodb.ScanInput, optFns ...func(*dynamodb.Options)) (*dynamodb.ScanOutput, error)
    }

and here could be your mocks

type mockDynamodb struct {
	rbaws.DynamoAPI
	*dynamodb.Client
	clientError error
}

func (m mockDynamodb) GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error) {

	return &dynamodb.GetItemOutput{
		Item: map[string]types.AttributeValue{},
	}, m.clientError
}

答案2

得分: 1

func (m mockDynamodb) GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error) {
    if (params.tablename == "eventDetails") {
        return m.eventDetailsItemOutput, m.clientError
    } else {
        return m.configItemOutput, m.clientError
    }
}

在测试文件中

DB := client.DynamoDBClient{
    Client: mockDynamoDB{
        eventDetailsItemOutput: dynamodb.GetItemOutput{
            Item: eventDetails,
        },
        configItemOutput: dynamodb.GetItemOutput{
            Item: eventDetails,
        },
        Error: tc.Error,
    },
}
英文:
func (m mockDynamodb) GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error) { 
 if (params.tablename == “eventDetails”) {     
  return m.eventDetailsItemOutput, m.clientError 
 } else {     
  return m.configItemOutput, m.clientError 
 } 
}

In test file

DB := client.DynamoDBClient{
 Client: mockDynamoDB{
   eventDetailsItemOutput: dynamodb.GetItemOutput{
     Item: eventDetails,
   },
   configItemOutput: dynamodb.GetItemOutput{
     Item: eventDetails,
   },
   Error: tc.Error,
  },
}

huangapple
  • 本文由 发表于 2021年11月12日 21:50:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/69943962.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定