首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用go-sqlmock创建gorm数据库(运行时错误)

使用go-sqlmock创建gorm数据库(运行时错误)
EN

Stack Overflow用户
提问于 2021-10-14 04:30:05
回答 1查看 1.6K关注 0票数 0

摘要

我正在尝试使用go-sqlmockgorm进行测试。我想为最初的数据库迁移编写一个测试,但是我已经命中了一个panic: runtime error: invalid memory address or nil pointer dereference,并且我一直很难找出原因。从错误堆栈判断,我认为是这个语句实现了它:db.AutoMigrate(&models.User{})。我不知道为什么,因为据称db在这一点上已经成功启动,而models.User被定义并实例化为db.AutoMigrate的一个参数。我有一种感觉,错误在mocks.NewDatabase函数中,但我感到很困惑。

不确定是否有人有时间或意愿在相关代码中达到峰值并帮助我解决问题?我在代码中注意到了故障发生的地方(它们位于最后两个代码块中)。请告诉我是否有任何额外的情况会有帮助。

相关守则

project/src/models/models.go

代码语言:javascript
复制
package models

import (
    "time"

    "github.com/google/uuid"
    "gorm.io/gorm"
)

type Base struct {
    ID        uuid.UUID      `json:"-" gorm:"primaryKey;type:uuid;not null"`
    CreatedAt time.Time      `json:"-" gorm:"autoCreateTime"`
    UpdatedAt time.Time      `json:"-" gorm:"autoUpdateTime"`
    DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}

type User struct {
    Base
    Name     string `json:"-"`
    Email    string `json:"-" gorm:"unique_index:user_email_index"`
    Password string `json:"-" gorm:"size:72"`
}

project/src/mocks/database.go

代码语言:javascript
复制
package mocks

import (
    "project/src/models"
    "log"

    "github.com/DATA-DOG/go-sqlmock"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

func NewDatabase() (*gorm.DB, sqlmock.Sqlmock) {

    // get db and mock
    sqlDB, mock, err := sqlmock.New(
        sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp),
    )
    if err != nil {
        log.Fatalf("[sqlmock new] %s", err)
    }
    defer sqlDB.Close()

    // create dialector
    dialector := mysql.New(mysql.Config{
        Conn: sqlDB,
    DriverName: "mysql",
    })

    // a SELECT VERSION() query will be run when gorm opens the database
    // so we need to expect that here
    columns := []string{"version"}
    mock.ExpectQuery("SELECT VERSION()").WithArgs().WillReturnRows(
    mock.NewRows(columns).FromCSVString("1"),
    )

    // open the database
    db, err := gorm.Open(dialector, &gorm.Config{ PrepareStmt: true })
    if err != nil {
        log.Fatalf("[gorm open] %s", err)
    }

  return db, mock
}

project/src/database/init.go

代码语言:javascript
复制
package database

import (
    "project/src/models"

    "gorm.io/gorm"
)

// Init auto-migrates the DB.
func Init(db *gorm.DB) {
    // Migrate the schema
    // this panics with
    // panic: runtime error: invalid memory address or nil pointer dereference
    // User is defined and instantiated here
    db.AutoMigrate(&models.User{})
}

现在测试:

project/src/database/init_test.go

代码语言:javascript
复制
package database

import (
    "project/src/mocks"
    "testing"
)

func TestInitMigratesDB(t *testing.T) {
    db, mock := mocks.NewDatabase()
    mock.ExpectExec("CREATE TABLE users(.*)")
    mock.ExpectCommit()
    
    // fails here
    Init(db)
}

还有原木

代码语言:javascript
复制
Running tool: /usr/local/go/bin/go test -timeout 30s -run ^TestInitMigratesDB$ project/src/database

--- FAIL: TestInitMigratesDB (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference
    panic: runtime error: invalid memory address or nil pointer dereference [recovered]
    panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x11ce22e]

goroutine 35 [running]:
testing.tRunner.func1.2({0x1505320, 0x19bfb00})
    /usr/local/go/src/testing/testing.go:1209 +0x24e
testing.tRunner.func1()
    /usr/local/go/src/testing/testing.go:1212 +0x218
panic({0x1505320, 0x19bfb00})
    /usr/local/go/src/runtime/panic.go:1038 +0x215
database/sql.(*Rows).close(0x0, {0x0, 0x0})
    /usr/local/go/src/database/sql/sql.go:3267 +0x8e
database/sql.(*Rows).Close(0x1e)
    /usr/local/go/src/database/sql/sql.go:3263 +0x1d
panic({0x1505320, 0x19bfb00})
    /usr/local/go/src/runtime/panic.go:1038 +0x215
database/sql.(*Rows).Next(0x0)
    /usr/local/go/src/database/sql/sql.go:2944 +0x27
database/sql.(*Row).Scan(0xc0000afbd8, {0xc0000efb38, 0x11, 0x1})
    /usr/local/go/src/database/sql/sql.go:3333 +0xb4
gorm.io/gorm/migrator.Migrator.CurrentDatabase({{0x0, 0xc000483350, {0x1659c58, 0xc00041a0f0}}})
    /go/pkg/mod/gorm.io/gorm@v1.21.15/migrator/migrator.go:673 +0x8d
gorm.io/gorm/migrator.Migrator.HasTable.func1(0xc0000f8380)
    /go/pkg/mod/gorm.io/gorm@v1.21.15/migrator/migrator.go:265 +0x51
gorm.io/gorm/migrator.Migrator.RunWithValue({{0x80, 0xc000483260, {0x1659c58, 0xc00041a0f0}}}, {0x1512320, 0xc0004fe2a0}, 0xc0000efcb8)
    /go/pkg/mod/gorm.io/gorm@v1.21.15/migrator/migrator.go:50 +0x126
gorm.io/gorm/migrator.Migrator.HasTable({{0x0, 0xc000483260, {0x1659c58, 0xc00041a0f0}}}, {0x1512320, 0xc0004fe2a0})
    /go/pkg/mod/gorm.io/gorm@v1.21.15/migrator/migrator.go:264 +0xe8
gorm.io/gorm/migrator.Migrator.AutoMigrate({{0x0, 0xc000426f90, {0x1659c58, 0xc00041a0f0}}}, {0xc00040f690, 0x0, 0x0})
    /go/pkg/mod/gorm.io/gorm@v1.21.15/migrator/migrator.go:92 +0x127
gorm.io/gorm.(*DB).AutoMigrate(0x151a800, {0xc00040f690, 0x1, 0x1})
    /go/pkg/mod/gorm.io/gorm@v1.21.15/migrator.go:26 +0x43
project/src/database.Init(0xc00041c230)
    /Projects/project/src/database/init.go:12 +0x7b
project/src/database.TestInitMigratesDB(0x0)
    /Projects/project/src/database/init_test.go:12 +0x5a
testing.tRunner(0xc0003a21a0, 0x15b5328)
    /usr/local/go/src/testing/testing.go:1259 +0x102
created by testing.(*T).Run
    /usr/local/go/src/testing/testing.go:1306 +0x35a
FAIL    project/src/database    0.276s
FAIL
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-14 18:02:27

弄明白了。它是一个配置选项:&gorm.Config{ PrepareStmt: true }。虽然这在生产中有效,但它不适用于sqlmock。通过将它更改为:&gorm.Config{}来修正它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69565095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档