英文:
httptest.NewRequest issues with query parameters
问题
我正在使用GIN框架与Postgres数据库和GORM作为ORM。
其中一个路由接受查询参数。当我在浏览器中搜索时,会得到预期的结果:一个JSON对象数组。以下是该路由:
/artworks/?limit=10&last_id=1
然而,当我尝试测试该路由使用的处理程序时,我得到以下错误:
routes_test.go:184: [ERROR] 无法将数据解组为artworks:json:无法将对象解组为类型为[]models.Artwork的Go值
ORM在测试函数中尝试运行的查询是:
SELECT * FROM "artwork_migrate_artwork" WHERE id = ''
所以当我在浏览器中运行请求时,它正确地提取查询参数,然后ORM运行正确的SQL查询。但是当使用httptest.NewRequest时,似乎没有使用查询参数。
这是我的测试函数:
func TestGetArtworks(t *testing.T) {
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=%s TimeZone=%s", env_var.Host, env_var.User, env_var.Password, env_var.DBname, env_var.Port, env_var.SSLMODE, env_var.TimeZone)
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect to db")
}
route := "/artworks/"
handler := handlers.GetArtwork(db)
router := setupGetRouter(handler, route)
writer := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/artworks/?limit=10&last_id=1", nil)
fmt.Println(req)
router.ServeHTTP(writer, req)
assert.Equal(t, 200, writer.Code)
data, err := ioutil.ReadAll(writer.Body)
if err != nil {
t.Errorf("\u001b[31m[Error] 无法读取writer.Body:%s", err)
}
// 无法解组body
fmt.Println("这是body:", writer.Body.String())
var artworks []models.Artwork
if err := json.Unmarshal(data, &artworks); err != nil {
t.Errorf("\u001b[31m[ERROR] 无法将数据解组为artworks:%s", err)
}
assert.Equal(t, 10, len(artworks))
}
这是我的路由处理程序:
func GetArtworks(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
limit, err := strconv.Atoi(c.Query("limit"))
if err != nil {
panic(err)
}
last_id := c.Query("last_id")
var artworks []models.Artwork
db.Where("id > ?", last_id).Limit(limit).Find(&artworks)
c.JSON(http.StatusOK, artworks)
}
}
router.GET("/artworks", han.GetArtworks(db))
这是模型结构:
type Artwork struct {
ID int `json:"id"`
Title string `json:"title"`
Nationality string `json:"nationality"`
Artist_Bio string `json:"artist_bio"`
Desc string `json:"desc"`
Culture string `json:"culture"`
Gender string `json:"gender"`
Nation string `json:"nation"`
Medium string `json:"medium"`
Date_of_Release string `json:"date_of_release"`
Image string `json:"image"`
Image_Small string `json:"image_small"`
Last_Modified time.Time `json:"last_modified"`
Artist_ID int `json:"artist_id"`
Source_ID int `json:"source_id"`
}
英文:
I'm using the GIN framework with a Postgres DB and GORM as an ORM.
One of the routes accepts query parameters. When I search for this in my browser, I get the expected results: an array of json objects. Here is the route:
/artworks/?limit=10&last_id=1
However, when I try to test the handler used by that route, I get the following error:
routes_test.go:184: [ERROR] Unable to unmarshal data to artworks: json: cannot unmarshal object into Go value of type []models.Artwork
The query that the ORM is trying to run in the test function is the folowing:
SELECT * FROM "artwork_migrate_artwork" WHERE id = ''
So when I run the request in the browser, it properly pulls the query parameters and then the ORM runs the proper sql query. But when using httptest.NewRequest it seems like the query parameters are not used.
Here is my test function:
func TestGetArtworks(t *testing.T) {
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=%s TimeZone=%s", env_var.Host, env_var.User, env_var.Password, env_var.DBname, env_var.Port, env_var.SSLMODE, env_var.TimeZone)
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect to db")
}
route := "/artworks/"
handler := handlers.GetArtwork(db)
router := setupGetRouter(handler, route)
writer := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/artworks/?limit=10&last_id=1", nil)
fmt.Println(req)
router.ServeHTTP(writer, req)
assert.Equal(t, 200, writer.Code)
data, err := ioutil.ReadAll(writer.Body)
if err != nil {
t.Errorf("\u001b[31m[Error] Unable to read writer.Body: %s", err)
}
// no body can be unmarshalled
fmt.Println("Here is the body:", writer.Body.String())
var artworks []models.Artwork
if err := json.Unmarshal(data, &artworks); err != nil {
t.Errorf("\u001b[31m[ERROR] Unable to unmarshal data to artworks: %s", err)
}
assert.Equal(t, 10, len(artworks))
}
Here is my route handler:
func GetArtworks(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
limit, err := strconv.Atoi(c.Query("limit"))
if err != nil {
panic(err)
}
last_id := c.Query("last_id")
var artworks []models.Artwork
db.Where("id > ?", last_id).Limit(limit).Find(&artworks)
c.JSON(http.StatusOK, artworks)
}
}
router.GET("/artworks", han.GetArtworks(db))
Here is the model struct:
type Artwork struct {
ID int `json:"id"`
Title string `json:"title"`
Nationality string `json:"nationality"`
Artist_Bio string `json:"artist_bio"`
Desc string `json:"desc"`
Culture string `json:"culture"`
Gender string `json:"gender"`
Nation string `json:"nation"`
Medium string `json:"medium"`
Date_of_Release string `json:"date_of_release"`
Image string `json:"image"`
Image_Small string `json:"image_small"`
Last_Modified time.Time `json:"last_modified"`
Artist_ID int `json:"artist_id"`
Source_ID int `json:"source_id"`
}
答案1
得分: 0
@Brits 是正确的:这是由于一个拼写错误的处理程序引起的
handler := handlers.GetArtwork(db)
应该是 handler := handlers.GetArtworks(db)
英文:
@Brits is correct: It was due to a misspelled handler
handler := handlers.GetArtwork(db)
should have been handler := handlers.GetArtworks(db)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论