测试包含对 sql.Open 连接的调用的 Golang 函数,无需数据库

pet*_*es_ 7 go

所以我刚刚开始掌握 Golang。我正在为 funsies 编写一个应用程序,只是为了理解并理解它。

我有一大堆函数将与数据库交互,我在数据库中传入*SQL.DB要使用的函数。我可以使用sqlmock的模拟接口轻松测试这些内容。

那里没问题。

我现在正在为应用程序编写初始化函数,该函数将启动数据库连接,该连接将附加到结构并从那里传递到实用程序函数。

然而,我正在努力寻找一种方法来轻松测试该连接,而无需设置实际数据库的麻烦。

所以我猜我的应用程序结构可能很糟糕,或者我错过了一些可能非常明显的东西。

所以这里有一些示例代码来说明我的困境。

util.go

package main
import (
    "log"
    "database/sql"
    "github.com/go-sql-driver/mysql"
)

func DoDBStuff(db *sql.DB) {
    rows, err := db.Query("SELECT column1, column2 FROM example")
    if err != nil {
       log.Error(err)
    }
    // do stuff with rows
}
Run Code Online (Sandbox Code Playgroud)

util_test.go

package main

import (
    "testing"
    "github.com/DATA-DOG/go-sqlmock"
)

func TestDoDBStuff(t *testing.T) {
    db, mock, err := sqlmock.New()
    if err != nil {
        t.Fatalf("An error '%s' was not expected when opening a stub database connection", err)
    }
    defer db.Close()

    rows := sqlmock.NewRows([]string{"col1", "col2"})
    rows.AddRow("val1", "val2")
    rows.AddRow("val3", "val4")

    mock.ExpectQuery("^SELECT column1, column2 from example$").WillReturnRows(rows)

    DoDBStuff(db)

    if err := mock.ExpectationsWereMet(); err != nil {
        t.Errorf("there were unfulfilled expectations: %s", err)
    }

}
Run Code Online (Sandbox Code Playgroud)

一切正常,我可以测试我的数据库查询。

但是现在我想测试初始化​​应用程序。

package main

import (
    "database/sql"
    "github.com/go-sql-driver/mysql"
)

type App {
    DB *sql.DB
    // some other data structures
}

func (a *App) InitApp(connectionString string) {
    a.DB = sql.Open("mysql", connectionString)
    // other init stuff
}
Run Code Online (Sandbox Code Playgroud)

但由于我无法通过,SQL我认为它不能被嘲笑,当然不容易。所以我在如何前进方面有些挣扎。

我打算将其置于休息 API 后面,因此在启动时,应用程序需要先进行初始化,然后才能处理任何请求。

理想情况下,我希望能够测试 REST 接口,而无需设置数据库,延迟使用真实数据进行测试,直到我可以将代码输入到开发环境中。

所以我真的想知道:

我的意图可能吗?有更好的方法吗?

如果不是我错过了什么?糟糕的测试设计或糟糕的代码设置?

编辑:

我只是想澄清一下@peter 的评论。

我想测试该函数的功能InitDB(),但通过sql.Open调用,我需要有一个数据库才能连接到,如果不这样做,调用就会失败,并且无法有效地测试该函数。

cha*_*360 4

Dockertest可以创建一个运行您想要的任何内容的 Docker 容器(即 MySQL),您可以对其进行测试。它的设计目的是能够进行适当的集成测试,因此它应该能够执行您想要的操作(您也不再需要sqlmock)。