Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Ujian unit untuk Context.Redirect gin berfungsi untuk kod respons GET tetapi bukan untuk kod respons POST (golang)

Ujian unit untuk Context.Redirect gin berfungsi untuk kod respons GET tetapi bukan untuk kod respons POST (golang)

WBOY
WBOYke hadapan
2024-02-10 19:27:081124semak imbas

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

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.

Kandungan soalan

Saya mahu pelayan saya mengubah hala titik akhir tertentu ke pelayan lain. Titik akhir ini boleh getted 或 posted。在这两种情况下,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

tl;dr

Penyelesaian ada di context.redirect 之后显式调用 context.writer.writeheadernow.

Arahan

Ini adalah kes kelebihan menggunakan konteks gin yang dikembalikan daripada gin.createtestcontext.

Untuk mendapatkan permintaan, gin akhirnya akan memanggil http.redirect ,它将向响应写入一个简短的 html 正文(类似于 64ac7c208db62edaa9346a44958f6a3efound5db79b134e9f6b82c0b36e0489ee08ed ), 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!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam