Apabila menulis aplikasi web dalam bahasa Go, kami sering menggunakan rangka kerja gin untuk mengendalikan permintaan dan respons HTTP. Semasa menjalankan ujian unit, kami perlu melakukan ujian liputan pada kod untuk memastikan kualiti dan kestabilan kod. Walau bagaimanapun, ujian unit untuk kaedah Context.Redirect gin berfungsi dengan baik apabila mengendalikan permintaan GET, tetapi tidak begitu baik apabila mengendalikan permintaan POST. Dalam artikel ini, editor PHP Apple akan menerangkan secara terperinci mengapa masalah ini berlaku dan menyediakan beberapa penyelesaian kepada permintaan POST ujian unit.
Saya mahu pelayan saya mengubah hala titik akhir tertentu ke pelayan lain. Titik akhir ini boleh get
ted 或 post
ed。在这两种情况下,http 响应代码都应为 302。如果我在此代码上使用 curl
,它确实在两种情况下都显示响应代码 302,并且 curl -l
untuk mengikuti ubah hala dengan betul. Wah.
Tetapi
Ujian unit saya menggunakan httptest.newrecorder()
来捕获信息,但它仅适用于get
,不适用于post
。因此,当我知道实际的重定向正在工作时,我需要弄清楚如何让单元测试工作。失败测试显示http响应代码是200而不是302(http.statusfound
).
$ go run foo.go post code 200 get code 302
Ini adalah ujian bebas.
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") } }
Apabila saya melaksanakan siaran curl pada aplikasi sebenar (tidak ditunjukkan) saya melihat bahawa ia berfungsi:
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
Penyelesaian ada di context.redirect
之后显式调用 context.writer.writeheadernow
.
Ini adalah kes kelebihan menggunakan konteks gin yang dikembalikan daripada gin.createtestcontext
.
Untuk mendapatkan permintaan, gin akhirnya akan memanggil http.redirect
,它将向响应写入一个简短的 html 正文(类似于 <a href="http://foobar.com">found</a>
), menyebabkan kod status respons ditulis.
Untuk permintaan kiriman, http.redirect
badan html pendek tidak ditulis, dan kod status tidak mempunyai peluang untuk ditulis untuk respons.
Lihat pelaksanaan http.redirect. Mengikut kod sumber, jika pengepala content-type
ditetapkan sebelum ini, masalah yang sama akan berlaku dengan permintaan get:
{ 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") }
Penyelesaian adalah dengan memanggil secara eksplisit context.writer.writeheadernow
:
{ 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 sendiri menggunakan penyelesaian yang sama. Lihat testcontextrenderredirectwithrelativepath.
Aplikasi pelayan sebenar tidak akan mengalami masalah yang sama seperti (*engine).handlehttprequest
将为我们调用 writeheadernow
(lihat kod sumber). Itulah sebabnya saya memanggilnya sebagai "kes tepi" dan bukannya "pepijat".
Atas ialah kandungan terperinci Ujian unit untuk Context.Redirect gin berfungsi untuk kod respons GET tetapi bukan untuk kod respons POST (golang). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!