使用go-sqlmock测试时无法自定义INSERT数据的问题
解决GORM INSERT测试中字段不匹配及自定义数据插入问题
核心问题分析
从报错信息可定位两个关键问题:
- SQL预期不匹配:GORM默认自动维护
created_at、updated_at、deleted_at字段(时间追踪+软删除特性),实际执行的INSERT语句包含这些字段,但你的sqlmock预期仅匹配name和description,导致匹配失败触发事务回滚。 - 自定义数据未传入:测试代码中注释了请求Body,POST请求未携带自定义的name和description,最终插入空值。
具体修复步骤
1. 修正sqlmock的INSERT预期
调整预期SQL的正则匹配规则,适配GORM自动生成的字段,同时用sqlmock.AnyArg()匹配动态生成的时间值:
// 替换原INSERT预期代码 mock.ExpectBegin() // 匹配包含所有字段的INSERT语句,注意转义反引号和括号 mock.ExpectExec(`INSERT INTO \`projects\` \(`created_at`,`updated_at`,`deleted_at`,`name`,`description`\)`). // 前三个参数为GORM自动生成的动态值,用AnyArg()匹配;后两个为自定义数据 WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), "测试项目", "测试描述"). WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectCommit()
2. 启用自定义请求数据
取消测试中请求Body的注释,确保POST请求携带合法JSON数据:
apitest.New(). Debug(). Handler(r). Post("/project"). // 传入自定义的项目数据 Body(`{"name": "测试项目", "description": "测试描述"}`). Expect(t). Status(http.StatusOK). End()
3. 完善HTTP请求处理逻辑
原CreateProject是结构体方法,需补充HTTP Handler完成请求体到Project实例的绑定,否则无法获取请求中的自定义数据:
// 新增HTTP Handler函数 func CreateProjectHandler(db *gorm.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var project Project // 解析请求体到Project结构体 if err := json.NewDecoder(r.Body).Decode(&project); err != nil { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]string{"error": "请求参数错误"}) return } // 调用CreateProject方法执行插入 if errResp := project.CreateProject(db); errResp != nil { w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(errResp) return } // 返回成功响应 w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(project) } } // 测试中注册路由时使用该Handler r.HandleFunc("/project", CreateProjectHandler(gormDB)).Methods("POST")
额外说明
- 若不需要GORM的时间追踪和软删除特性,可在初始化时关闭:
gormDB, err := gorm.Open(mysql.New(mysql.Config{ Conn: db, SkipInitializeWithVersion: true, }), &gorm.Config{ // 关闭自动时间戳 DisableAutomaticTimeStamp: true, // 关闭软删除 DisableForeignKeyConstraintWhenMigrating: true, }) - 测试中
mock.ExpectationsWereMet()应放在测试流程最后(如End()之后),提前调用会干扰后续数据库操作的预期验证。
内容的提问来源于stack exchange,提问作者JonB
相关产品推荐
相关产品推荐

