使用Echo测试用户注册遇Gorm类型错误:*gorm.DB无法赋值为error
问题描述
在使用Echo框架测试用户注册功能时遇到错误,错误信息:
cannot use r.Create(id, name, password, email) (value of type "*gorm.io/gorm".DB) as error value in assignment: "*gorm.io/gorm".DB does not implement error
以下是相关代码:
测试代码
package test import ( "regexp" "testing" sqlmock "github.com/DATA-DOG/go-sqlmock" "github.com/...../model" "github.com/jinzhu/gorm" ) func getDBMock() (*gorm.DB, sqlmock.Sqlmock, error) { db, mock, err := sqlmock.New() if err != nil { return nil, nil, err } gdb, err := gorm.Open("postgres", db) if err != nil { return nil, nil, err } return gdb, mock, nil } func TestCreate(t *testing.T) { db, mock, err := getDBMock() if err != nil { t.Fatal(err) } defer db.Close() db.LogMode(true) r := model.Repository{DB: db} id := "2222" name := "BBBB" password := "mfsdmSD34" email := "dmvsdmvo@.com" // Mock設定 mock.ExpectQuery(regexp.QuoteMeta( `INSERT INTO "users" ("id","name","passowrd","email") VALUES ($1,$2,$3,$4) RETURNING "users"."id"`)).WithArgs(id, name,password,email). WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(id)) // 実行 err = r.Create(id, name,password,email) if err != nil { t.Fatal(err) } }
Model层User结构代码
package model type User struct { ID int `json:"id" gorm:"praimaly_key"` Name string `json:"name"` Password string `json:"password"` Email string `json:"email"` } func CreateUser(user *User) { db.Create(user) } func FindUser(u *User) User { var user User db.Where(u).First(&user) return user }
Model层数据库初始化代码
package model import ( "gorm.io/driver/mysql" "gorm.io/gorm" ) var db *gorm.DB func init() { var err Error dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") } db.AutoMigrate(&User{}) db.AutoMigrate(&Todo{}) }
错误原因与修复步骤
核心错误原因
你把r.Create()的返回值(*gorm.DB类型)直接赋值给err变量(error类型),但GORM的Create方法返回的是DB实例而非error;同时测试代码中使用的model.Repository结构体在现有Model代码中未定义,导致方法实现不匹配,最终触发类型错误。
以下是具体修复步骤:
1. 补充Model层的Repository结构体与Create方法
在Model层添加Repository结构体用于依赖注入DB实例,并实现返回错误的Create方法:
package model import "gorm.io/gorm" // 定义Repository结构体,用于测试时注入Mock DB type Repository struct { DB *gorm.DB } // 实现Create方法,接收参数创建User并返回错误 func (r *Repository) Create(id int, name, password, email string) error { user := User{ ID: id, Name: name, Password: password, Email: email, } // 从GORM的DB实例中提取错误返回 return r.DB.Create(&user).Error }
2. 修正User结构体的GORM标签拼写错误
将praimaly_key修正为正确的primaryKey:
type User struct { ID int `json:"id" gorm:"primaryKey"` Name string `json:"name"` Password string `json:"password"` Email string `json:"email"` }
3. 统一GORM依赖并修正测试代码错误
- 测试代码中导入的
github.com/jinzhu/gorm需替换为gorm.io/gorm,与Model层保持一致 - SQL语句中
passowrd拼写错误修正为password - 测试中的id改为int类型,匹配User结构体的ID字段类型
- 修正DB关闭方式,添加Mock预期验证:
package test import ( "regexp" "testing" sqlmock "github.com/DATA-DOG/go-sqlmock" "github.com/...../model" "gorm.io/gorm" "gorm.io/driver/postgres" ) func getDBMock() (*gorm.DB, sqlmock.Sqlmock, error) { db, mock, err := sqlmock.New() if err != nil { return nil, nil, err } gdb, err := gorm.Open(postgres.New(postgres.Config{ Conn: db, }), &gorm.Config{}) if err != nil { return nil, nil, err } return gdb, mock, nil } func TestCreate(t *testing.T) { db, mock, err := getDBMock() if err != nil { t.Fatal(err) } defer func() { sqlDB, _ := db.DB() sqlDB.Close() }() db.LogMode(true) r := model.Repository{DB: db} id := 2222 name := "BBBB" password := "mfsdmSD34" email := "dmvsdmvo@.com" mock.ExpectQuery(regexp.QuoteMeta( `INSERT INTO "users" ("id","name","password","email") VALUES ($1,$2,$3,$4) RETURNING "users"."id"`)).WithArgs(id, name,password,email). WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(id)) err = r.Create(id, name,password,email) if err != nil { t.Fatal(err) } // 验证所有Mock预期是否执行完成 if err := mock.ExpectationsWereMet(); err != nil { t.Fatalf("未满足所有Mock预期: %v", err) } }
4. 修正Model初始化代码的错误
将var err Error改为var err error:
package model import ( "gorm.io/driver/mysql" "gorm.io/gorm" ) var db *gorm.DB func init() { var err error dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") } db.AutoMigrate(&User{}) db.AutoMigrate(&Todo{}) }
内容的提问来源于stack exchange,提问作者assa
相关产品推荐
相关产品推荐

