如何触发*mongo.SingleResult的Decode方法报错?
触发MongoDB SingleResult解码失败的测试方案
要让*mongo.SingleResult的Decode方法报错,核心是让Mock返回的BSON数据与目标结构体models.Shop的字段类型完全不兼容。以下是具体实现步骤:
关键思路
MongoDB的解码报错通常源于:
- 字段类型不匹配(比如把字符串赋值给数字类型字段)
- 无效的BSON类型转换(比如把普通字符串赋值给
primitive.ObjectID类型) - 结构体中必填的嵌套字段被赋值为非结构体类型
修改后的测试代码
假设你的models.Shop结构体包含_id(primitive.ObjectID类型)、Name(字符串)、Rating(float64)这类字段,我们可以通过返回无效的ObjectID字符串或类型不匹配的字段值来触发解码错误:
func TestRepository_Get_Bad_Parse_Error(t *testing.T) { mock := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock)) mock.Cleanup(func() { mock.Client = nil }) mock.Run("BadParseError", func(mock *mtest.T) { repository := shops.NewRepositoryImpl(mock.DB.Collection(dependencies.KvsShopsCollection)) // 返回包含类型不匹配字段的文档: // 1. _id传非ObjectID格式的字符串(无法转换为primitive.ObjectID) // 2. Rating传字符串(无法转换为float64) mock.AddMockResponses(mtest.CreateCursorResponse(0, "foo.bar", mtest.FirstBatch, bson.D{ {"_id", "invalid-object-id-string"}, // 无效的ObjectID,触发解码失败 {"Name", "Test Shop"}, {"Rating", "not-a-number"}, // 字符串赋值给数字字段,触发类型不匹配 },),) shopTest, err := repository.Get(context.TODO(), "65f4973cb7942e76f0aa85c5") assert.EqualValues(mock, models.Shop{}, shopTest) assert.NotNil(t, err) // 可以进一步断言错误类型,比如是bson解码错误 assert.ErrorContains(t, err, "cannot decode") }) }
原理说明
当Mock返回的BSON文档中,某个字段的类型与models.Shop对应字段的Go类型无法转换时,result.Decode(&mdls)就会抛出bson.DecodeError,进而触发你代码中对应的错误分支。
比如:
- 如果
_id字段定义为primitive.ObjectID,传入非24位十六进制字符串会导致解码失败 - 如果
Rating是float64类型,传入字符串值会触发类型不匹配错误
注意事项
- 要根据你实际的
models.Shop结构体字段类型来选择不兼容的BSON值,确保解码时必然失败 - 不需要使用
CreateWriteErrorsResponse,因为它模拟的是写入错误,而非解码错误
内容的提问来源于stack exchange,提问作者Agustín Rabini
相关产品推荐
相关产品推荐

