Go 测试失败数据库查询(无指针)但适用于 Postman/Curl

Go test fails db query (nil pointer) but works with Postman/Curl

我正在测试 GetCats(),这是一个从 mysql 数据库中获取所有 'cats' 的函数。当我通过邮递员到达端点时,由于 'COALESCE' 没有 nil 指针错误,如果为空,则将字段设置为空字符串。

但是,当我测试函数时,出现nil指针错误,程序崩溃。

_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")

    //------------------------------------------------//

如有任何帮助,我们将不胜感激!

补充说明:

可能是Db对象在测试中没有正确初始化。您最好定义一个结构并将 DB 作为依赖项注入,并在测试中使用伪造的 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)
        }
}