You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 13:55:20