httptest.NewRequest在处理查询参数时存在问题。

huangapple go评论82阅读模式
英文:

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)

huangapple
  • 本文由 发表于 2022年8月8日 21:07:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/73278389.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定