例如,当我使用gomock测试使用DynamoDB的代码时,如下所示:
mockDynamoDB := awsmock.NewMockDynamoDBAPI(ctrl)
mockDynamoDBClient.EXPECT().PutItemWithContext(gomock.Any(),
gomock.Any() // Here I should use a custom matcher for comparing PutItemInput
).Return(&dynamodb.PutItemOutput{...}, nil).Times(1)
// do something which will internally call PutItemWithContext
避免使用
gomock.Any()
在所有地方,我认为我应该为
PutItemInput
然而,这似乎有点困难,因为
PutItem输入
序列化很复杂
Item map[string]*AttributeValue
,我需要像这样逐一比较,但我不喜欢这个实现。
func (piim dynamodbPutItemInputEqualMatcher) Matches(x interface{}) bool {
input, ok := x.(*dynamodb.PutItemInput)
if !ok {
return false
}
if input.TableName != nil && piim.expectedInput.TableName != nil && *input.TableName != *pie.expectedInput.TableName {
return false
}
for attributeName, attributeValue := range input.Item {
exptectedAttributeValue, ok := piim.expectedInput.Item[attributeName]
if !ok {
return false
}
if attributeValue.N != nil && exptectedAttributeValue.N != nil && *attributeValue.N != *exptectedAttributeValue.N {
return false
}
if attributeValue.S != nil && exptectedAttributeValue.S != nil && *attributeValue.S != *exptectedAttributeValue.S {
return false
}
if attributeValue.BOOL != nil && exptectedAttributeValue.BOOL != nil && *attributeValue.BOOL != *exptectedAttributeValue.BOOL {
return false
}
if attributeValue.NULL != nil && exptectedAttributeValue.NULL != nil && *attributeValue.NULL != *exptectedAttributeValue.NULL {
return false
}
if attributeValue.B != nil || attributeValue.NS != nil || attributeValue.SS != nil || attributeValue.BS != nil || attributeValue.L != nil || attributeValue.M != nil {
return false
}
}
return true
}
DynamoDB还有其他API,如
GetItem
,
ScanPages
等等,。我需要为每种类型的输入结构实现自定义匹配器。
我们是否有更好的方法将gomock与AWS结合使用?谢谢。
===========================================
我不认为我的案例过度使用mocking,我的代码不仅仅是DynamoDB调用的简单包装器,它实现了我自己的业务逻辑,如果需要,最后会写入DynamoDB。我想将DynamoDB与我的单元测试隔离开来有几个原因。
(1) 要使用真正的DynamoDB进行测试,我需要在Jenkins中运行单元测试之前设置有效的creds,并保持creds的维护,此外,执行单元测试的环境必须有互联网连接,这很难,有时甚至是不可能的。
(2) 我只是想在单元测试中验证我的业务逻辑。例如,函数需要首先验证输入参数,当用户输入无效时,立即返回错误,单元测试应该涵盖这一点,这与DynamoDB完全无关。这里的测试用例主要关注我的业务逻辑,即当输入不同的输入时,业务逻辑是否按预期工作,而不是验证DynamoDB是否可靠,因此可以合理地假设DynamoDB在我的单元测试中始终按预期运行。
(3) 集成测试的范围/目标是在将我的业务逻辑与真实的DynamoDB结合在一起时测试功能,我们已经对此进行了综合测试,单元测试只是单元测试。如果我在测试中使用真实的DynamoDB,以防DynamoDB发生故障,或者Jenkins和DynamoDB之间的连接中断,UT失败,我不希望我的UT受到这种故障的影响。