Saya memiliki fungsi controller seperti ini ....

func GetMaterialByFilter(c *gin.Context) {

    queryParam := weldprogs.QueryParam{}
    c.BindQuery(&queryParam)
    materialByFilter, getErr := services.WeldprogService.GetMaterialByFilter(&queryParam)
    if getErr != nil {
        //TODO : Handle user creation error
        c.JSON(getErr.Status, getErr)
        return
    }
    c.JSON(http.StatusOK, materialByFilter)

}

Queryparam struct adalah seperti ini ..

type QueryParam struct {
    Basematgroup_id []string `form:"basematgroup_id"`
    License_id      []string `form:"license_id"`
    Diameter_id     []string `form:"diameter_id"`
    Gasgroup_id     []string `form:"gasgroup_id"`
    Wiregroup_id    []string `form:"wiregroup_id"`
    Wiremat_id      []string `form:"wiremat_id"`
}

Fungsi tes saya seperti ini ..

func TestGetMaterialByFilter(t *testing.T) {
    w := httptest.NewRecorder()
    c, _ := gin.CreateTestContext(w)
    GetMaterialByFilter(c)
    assert.Equal(t, 200, w.Code) 

    var got gin.H
    err := json.Unmarshal(w.Body.Bytes(), &got)
    if err != nil {
        t.Fatal(err)
    }
    fmt.Println(got)
    assert.Equal(t, got, got) 
}

Menjalankan tes ini memberi saya kesalahan berikut

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=0x10 pc=0x97f626]

Tetapi ketika saya mengomentari garis c.bindquery () dalam fungsi controller saya berhasil menjalankan fungsi tes saya. Apa yang saya lakukan salah di sini? Bisakah saya entah bagaimana mengejek fungsi c.bindquery?

2
Hsn 5 April 2021, 15:05

1 menjawab

Jawaban Terbaik

Untuk menguji operasi yang melibatkan permintaan HTTP, Anda harus benar-benar menginisialisasi *http.Request dan mengaturnya ke konteks gin. Untuk secara khusus menguji c.BindQuery itu cukup untuk menginisialisasi dengan benar URL dan URL.RawQuery:

func mockGin() (*gin.Context, *httptest.ResponseRecorder) {
    w := httptest.NewRecorder()
    c, _ := gin.CreateTestContext(w)

    // test request, must instantiate a request first
    req := &http.Request{
        URL:    &url.URL{},
        Header: make(http.Header), // if you need to test headers
    }
    // example: req.Header.Add("Accept", "application/json")

    // request query
    testQuery := weldprogs.QueryParam{/* init fields */}

    q := req.URL.Query()
    for _, s := range testQuery.Basematgroup_id {
        q.Add("basematgroup_id", s)
    }
    // ... repeat for other fields as needed

    // must set this, since under the hood c.BindQuery calls
    // `req.URL.Query()`, which calls `ParseQuery(u.RawQuery)`
    req.URL.RawQuery = q.Encode()
    
    // finally set the request to the gin context
    c.Request = req

    return c, w
}

Panggilan layanan services.WeldprogService.GetMaterialByFilter(&queryParam) tidak dapat diuji seperti itu. Untuk dapat diuji, ia harus (idealnya) antarmuka dan entah bagaimana disuntikkan sebagai ketergantungan pawang Anda.

Dengan asumsi bahwa itu sudah merupakan antarmuka, untuk membuatnya menjadi suntikan, Anda membutuhkannya sebagai argumen handler - tetapi ini memaksa Anda untuk mengubah tanda tangan pawang -, atau Anda mengaturnya sebagai nilai konteks GIN:

func GetMaterialByFilter(c *gin.Context) {
    //...
    weldprogService := mustGetService(c)
    materialByFilter, getErr := weldprogService.GetMaterialByFilter(&queryParam)
    // ...
}

func mustGetService(c *gin.Context) services.WeldprogService {
    svc, exists := c.Get("svc_context_key")
    if !exists {
        panic("service was not set")
    }
    return svc.(services.WeldprogService)
}

Maka Anda dapat mengejeknya dalam tes unit Anda:

type mockSvc struct {
}

// have 'mockSvc' implement the interface 

func TestGetMaterialByFilter(t *testing.T) {
    w := httptest.NewRecorder()
    c, _ := gin.CreateTestContext(w)

    // now you can set mockSvc into the test context
    c.Set("svc_context_key", &mockSvc{})

    GetMaterialByFilter(c)
    // ... 
}
2
blackgreen 5 April 2021, 16:16