Go 测试失败 db 查询(零指针)但适用于 Postman/Curl
Posted
技术标签:
【中文标题】Go 测试失败 db 查询(零指针)但适用于 Postman/Curl【英文标题】:Go test fails db query (nil pointer) but works with Postman/Curl 【发布时间】:2022-01-03 09:42:17 【问题描述】:我正在测试 GetCats(),这是一个从 mysql 数据库中获取所有“猫”的函数。当我通过邮递员到达端点时,由于 'COALESCE' 将字段设置为空字符串(如果为 null),因此不会出现 nil 指针错误。
但是,当我测试该函数时,出现了一个 nil 指针错误并且程序崩溃了。
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
_test.go
func TestGetCats(t *testing.T)
// create new request to /cats endpoint, nil => body io.Reader
req, err := http.NewRequest("GET", "/cats", nil)
if err != nil
t.Fatal(err)
// Will store response received from /cats endpoint => pointer to ResonseRecorder struct
recorder := httptest.NewRecorder()
handler := http.HandlerFunc(handlers.GetCats)
// ----(FAILS HERE) hit endpoint with recorder and request (FAILS HERE) ----//
handler.ServeHTTP(recorder, req)
// ------------------------------------------------------------------------//
// test recorder status code
if recorder.Code != http.StatusOK
t.Errorf("getCats return wrong status code: got %v but want %v", recorder.Code, http.StatusOK)
cathandlers.go
func GetCats(w http.ResponseWriter, r *http.Request)
w.Header().Set("Content-Type", "application/json")
var animals []Animal
// ---------------Program panics on this query --------------------//
// cannot input null values into struct => return empty string instead
res, err := Db.Query("SELECT id, name,
COALESCE(age, '') as age,
COALESCE(color, '') as color,
COALESCE(gender, '') as gender,
COALESCE(breed, '') as breed,
COALESCE(weight, '') as weight FROM cats")
//------------------------------------------------//
任何帮助将不胜感激!
补充说明:
'name' 在数据库中不为空,不需要在该字段上合并 数据库中有几个空字段(故意) 只是对查询在邮递员中的工作方式感到困惑,但在从 _test.go 内部调用时却没有【问题讨论】:
我的猜测是,这与查询本身没有太大关系,而是与Db
的初始化方式有关。也许它是由您的 main()
函数初始化的,在运行测试时不会执行。
谢谢@mkopriva,这正是问题所在
【参考方案1】:
可能 Db 对象在测试中未正确初始化。您最好定义一个结构并将数据库注入为依赖项,并在测试中使用假数据库对象。例如,
// handlers.go
import (
"database/sql"
"net/http"
)
type App struct
DB *sql.DB
func (a *App) GetCats(w http.ResponseWriter, r *http.Request)
// var animals []Animal
res, err := a.DB.Query("SELECT id, name,
COALESCE(age, '') as age,
COALESCE(color, '') as color,
COALESCE(gender, '') as gender,
COALESCE(breed, '') as breed,
COALESCE(weight, '') as weight FROM cats")
// ....
// handlers_test.go
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/DATA-DOG/go-sqlmock"
)
func TestGetCats(t *testing.T)
db, _, err := sqlmock.New()
if err != nil
t.Fatalf("an error %s was not expected when openning a stub database connection", err)
app := &App
DB: db,
req, err := http.NewRequest("GET", "/cats", nil)
if err != nil
t.Fatal(err)
// Will store response received from /cats endpoint => pointer to ResonseRecorder struct
recorder := httptest.NewRecorder()
// DB expected actions...
handler := http.HandlerFunc(app.GetCats)
handler.ServeHTTP(recorder, req)
if recorder.Code != http.StatusOK
t.Errorf("getCats return wrong status code: got %v but want %v", recorder.Code, http.StatusOK)
【讨论】:
感谢@Phuc,这真的很有帮助!以上是关于Go 测试失败 db 查询(零指针)但适用于 Postman/Curl的主要内容,如果未能解决你的问题,请参考以下文章
为啥 django test --keep-db 适用于 postgres 数据库但不适用于默认 sqlite3
Django 测试因 InternalError 失败:没有这样的保存点。 DB:Postgres,通过 mysql
angularJS ajax 调用失败 403 但 jQuery ajax 调用适用于跨站点 templateUrl 加载。 [复制]