Mongo-Driver mtest更新测试用例失效,请求技术排查
问题背景
使用Mongo-Driver的mtest编写DeleteUser测试函数,仅覆盖成功更新场景(更新user_rec集合并插入del_user_col集合),但测试用例无法正常执行。
具体问题及修复方案
1. Mock响应顺序与业务流程不匹配,且存在冗余响应
业务函数的核心执行流程是:FindOne(user_rec) → InsertOne(del_user_col) → UpdateOne(user_rec),而测试中额外添加了mockRemoveResponse(成功路径不会触发删除操作),多余的响应会导致mtest报错。
修复:移除多余的Mock响应添加语句,确保响应顺序严格匹配业务操作:
// 移除这一行冗余代码 // mt.AddMockResponses(tt.mockRemoveResponse)
2. FindOne的Mock响应不符合Projection要求
业务中FindOne使用了projection: {name:1},返回的文档应包含_id(Mongo默认返回)和name字段,但测试中仅序列化了model.User{Name: "temp"},缺失_id字段,导致业务函数执行FindOne时返回ErrNoDocuments,进而返回svc.ErrUnexpected,与预期的nil错误不符。
修复:构造包含_id和name的标准Mock文档:
// 替换原有的doc构造代码,直接构造符合要求的bson文档 doc := bson.D{ {"_id", uid}, {"name", tt.user.Name}, }
3. UpdateOne的Mock响应格式错误
测试中自定义的mockUpdateResponse包含多余的value字段(该字段属于FindOne响应),不符合Mongo UpdateOne的响应格式,会导致业务函数解析响应失败。
修复:使用mtest.CreateSuccessResponse()生成标准的UpdateOne成功响应,并设置nModified为1:
// 测试用例中的mockUpdateResponse改为 mockUpdateResponse: mtest.CreateSuccessResponse().SetDocument(bson.D{ {"nModified", 1}, }),
4. 两个业务集合复用同一个Mock集合
测试中将collUserRec和collDeletedUserRec都设为mt.Coll,导致两个集合的操作指向同一个Mock集合,虽当前场景下顺序能匹配,但不符合实际业务逻辑,易引发后续测试混淆。
修复:为两个集合创建独立的Mock集合,并在响应中指定集合名称:
mg := Mongo{ conn: &cMongo.Mongo{ Client: mt.Client, DB: mt.DB, }, logger: logger, collUserRec: mt.DB.Collection("user_rec"), collDeletedUserRec: mt.DB.Collection("del_user_col"), } // 添加Mock响应时指定对应集合 mt.AddMockResponses(mtest.CreateCursorResponse(1, "testDB.user_rec", mtest.FirstBatch, doc)) mt.AddMockResponses(mtest.CreateSuccessResponse().SetCollectionName("testDB.del_user_col")) mt.AddMockResponses(mtest.CreateSuccessResponse().SetCollectionName("testDB.user_rec").SetDocument(bson.D{{"nModified", 1}}))
5. 测试断言使用全局t而非mtest.T
测试中使用assert.Nil(t, err)和assert.Equal(t, tt.expectErr, err),但在mtest的子测试中应使用mt而非全局t,否则可能导致测试报告错误。
修复:将断言中的t替换为mt:
assert.Nil(mt, err) // ... assert.Equal(mt, tt.expectErr, err)
内容的提问来源于stack exchange,提问作者Utkarsh Saxena

