首頁 > 後端開發 > Golang > gin 的 Context.Redirect 的單元測試適用於 GET 回應代碼,但不適用於 POST 回應代碼 (golang)

gin 的 Context.Redirect 的單元測試適用於 GET 回應代碼,但不適用於 POST 回應代碼 (golang)

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
發布: 2024-02-10 19:27:08
轉載
1415 人瀏覽過

gin 的 Context.Redirect 的单元测试适用于 GET 响应代码,但不适用于 POST 响应代码 (golang)

在使用Go語言編寫Web應用程式時,我們經常會用到gin框架來處理HTTP請求和回應。在進行單元測試時,我們需要對程式碼進行覆蓋測試,以確保程式碼的品質和穩定性。然而,針對gin的Context.Redirect方法的單元測試在處理GET請求時非常適用,但在處理POST請求時卻不太適用。在本文中,php小編蘋果將會詳細解釋為什麼這個問題會出現,並提供一些解決方案來進行POST請求的單元測試。

問題內容

我希望我的伺服器將特定端點重定向到另一台伺服器。這個端點可以是 getted 或 posted。在這兩種情況下,http 回應碼都應為 302。如果我在此程式碼上使用 curl ,它確實在兩種情況下都顯示回應代碼 302,並且 curl -l 正確遵循重定向。哇哦。

但是

我的單元測試使用httptest.newrecorder()來捕獲訊息,但它僅適用於get,不適用於post。因此,當我知道實際的重定向正在工作時,我需要弄清楚如何讓單元測試工作。失敗測試顯示http回應碼是200而不是302(http.statusfound)。

1

2

3

$ go run foo.go

post code 200

get code 302

登入後複製

這是獨立測試。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

package main

 

import (

    "net/http"

    "net/http/httptest"

    "github.com/gin-gonic/gin"

)

 

func main() {

    gin.setmode(gin.releasemode)

    {

        w := httptest.newrecorder()

        context, _ := gin.createtestcontext(w)

        context.request = httptest.newrequest("post", "http://localhost:23632/foobar", nil)

        context.redirect(http.statusfound, "http://foobar.com")

 

        print("post code ",w.code,"\n")

    }

 

    {

        w := httptest.newrecorder()

        context, _ := gin.createtestcontext(w)

        context.request = httptest.newrequest("get", "http://localhost:23632/foobar", nil)

        context.redirect(http.statusfound, "http://foobar.com")

 

        print("get code ",w.code,"\n")

    }

}

登入後複製

當我在實際應用程式(未顯示)上執行 curl post 時,我發現它正在工作:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

curl -v -XPOST localhost:23632/foobar

* About to connect() to localhost port 23632 (#0)

*   Trying 127.0.0.1...

* Connected to localhost (127.0.0.1) port 23632 (#0)

> POST /foobar HTTP/1.1

> User-Agent: curl/7.29.0

> Host: localhost:23632

> Accept: */*

>

< HTTP/1.1 302 Found

< Location: http://foobar.com

< Vary: Origin

< Date: Tue, 23 May 2023 22:38:42 GMT

< Content-Length: 0

<

* Connection #0 to host localhost left intact

登入後複製

解決方法

tl;dr

解決方法是在 context.redirect 之後明確呼叫 context.writer.writeheadernow

說明

這是使用從 gin.createtestcontext 傳回的 gin 上下文的一個極端情況。

對於get 請求,gin 最終會呼叫http.redirect ,它將向回應寫入一個簡短的html 正文(類似於<a href="http://foobar. com">found</a> ),從而導致要寫入回應的狀態碼。

對於 post 請求,http.redirect 不會寫入短 html 正文,且狀態碼沒有機會寫入回應。

請參考http 的實作.重定向。根據原始碼,如果之前設定了content-type header,那麼get請求也會出現相同的問題:

1

2

3

4

5

6

7

8

{

    w := httptest.newrecorder()

    context, _ := gin.createtestcontext(w)

    context.request = httptest.newrequest("get", "http://localhost:23632/foobar", nil)

+   context.header("content-type", "text/html")

    context.redirect(http.statusfound, "http://foobar.com")

    print("get code ", w.code, "\n")

  }

登入後複製

解決方法是明確呼叫 context.writer.writeheadernow

1

2

3

4

5

6

7

8

9

{

    w := httptest.NewRecorder()

    context, _ := gin.CreateTestContext(w)

    context.Request = httptest.NewRequest("POST", "http://localhost:23632/foobar", nil)

    context.Redirect(http.StatusFound, "http://foobar.com")

+   context.Writer.WriteHeaderNow()

 

    print("POST code ", w.Code, "\n")

  }

登入後複製

gin 本身使用相同的解決方法。請參閱 testcontextrenderredirectwithrelativepath

真正的伺服器應用程式不會遇到相同的問題,因為(*engine).handlehttprequest 將為我們呼叫writeheadernow (請參閱原始碼)。這就是為什麼我稱其為“極端情況”而不是“錯誤”。

以上是gin 的 Context.Redirect 的單元測試適用於 GET 回應代碼,但不適用於 POST 回應代碼 (golang)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板