如何为dynamodbattribute.UnmarshalMap编写抛错Mock测试
解决方案:抽象反序列化依赖实现Mock测试
要在不修改UpdateItem返回结果的前提下测试UnmarshalMap报错的场景,核心思路是把硬编码的dynamodbattribute.UnmarshalMap调用抽象为可注入的依赖,这样测试时就能用Mock实现直接抛出错误。
步骤1:定义反序列化接口
先创建一个接口封装UnmarshalMap的行为,让业务代码依赖这个接口而非具体实现:
import ( "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue" ) // DynamoDBUnmarshaler 定义DynamoDB属性反序列化的接口 type DynamoDBUnmarshaler interface { UnmarshalMap(attrs map[string]types.AttributeValue, out interface{}) error }
步骤2:实现默认的反序列化器
对应生产环境的默认实现,直接包装官方的UnmarshalMap函数:
// DefaultUnmarshaler 生产环境使用的默认反序列化器 type DefaultUnmarshaler struct{} func (u *DefaultUnmarshaler) UnmarshalMap(attrs map[string]types.AttributeValue, out interface{}) error { return attributevalue.UnmarshalMap(attrs, out) }
步骤3:修改业务函数,注入依赖
更新update函数,把DynamoDBUnmarshaler作为参数传入(也可以通过结构体成员注入,根据你的代码结构调整):
func update(ddbClient, unmarshaler DynamoDBUnmarshaler) { updatedItem, err := ddbClient.updateItem(...) if err != nil { // 处理updateItem的错误逻辑 return } obj := new(MyCustomObj) err = unmarshaler.UnmarshalMap(updatedItem.Attributes, &obj) if err != nil { fmt.Println("Error while unmarshalling") } }
步骤4:编写Mock测试用例
用Mock框架(比如github.com/stretchr/testify/mock)实现DynamoDBUnmarshaler接口,让它直接返回预设错误:
import ( "fmt" "testing" "github.com/stretchr/testify/mock" ) // MockUnmarshaler 用于测试的反序列化Mock type MockUnmarshaler struct { mock.Mock } func (m *MockUnmarshaler) UnmarshalMap(_ map[string]types.AttributeValue, _ interface{}) error { args := m.Called() return args.Error(0) } func TestUpdate_UnmarshalFailure(t *testing.T) { // 初始化你已有的DDB Client Mock mockDDB := // 你的DDB Client Mock实例,确保updateItem返回正常结果 // 初始化Mock反序列化器,预设返回错误 mockUnmarshaler := new(MockUnmarshaler) mockUnmarshaler.On("UnmarshalMap").Return(fmt.Errorf("mock unmarshal failure")) // 调用业务函数 update(mockDDB, mockUnmarshaler) // 验证错误处理逻辑是否触发(比如检查日志输出,或用断言验证行为) // 示例:如果用日志捕获,可以断言日志中包含指定错误信息 // assert.True(t, logOutputContains("Error while unmarshalling")) // 验证Mock的方法被正确调用 mockUnmarshaler.AssertExpectations(t) }
为什么这种方式可行?
- 避免了修改
UpdateItem返回的Attributes,不会影响其他依赖正常Attributes的测试场景 - 通过依赖注入解耦了业务代码与具体的反序列化实现,让测试可以精准控制反序列化环节的错误
- 符合Go语言的接口依赖设计原则,代码扩展性更好
内容的提问来源于stack exchange,提问作者NoSleepDev
相关产品推荐
相关产品推荐

