Unit-Test für Gins Context.Redirect funktioniert für GET-Antwortcodes, aber nicht für POST-Antwortcodes (Golang)

WBOY
Freigeben: 2024-02-10 19:27:08
nach vorne
1157 Leute haben es durchsucht

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

Beim Schreiben von Webanwendungen in der Go-Sprache verwenden wir häufig das Gin-Framework, um HTTP-Anfragen und -Antworten zu verarbeiten. Bei der Durchführung von Unit-Tests müssen wir Abdeckungstests für den Code durchführen, um die Qualität und Stabilität des Codes sicherzustellen. Der Komponententest für die Context.Redirect-Methode von Gin funktioniert jedoch gut bei der Verarbeitung von GET-Anfragen, jedoch nicht so gut bei der Verarbeitung von POST-Anfragen. In diesem Artikel erklärt der PHP-Editor Apple ausführlich, warum dieses Problem auftritt, und bietet einige Lösungen für Unit-Test-POST-Anfragen.

Frageninhalt

Ich möchte, dass mein Server einen bestimmten Endpunkt auf einen anderen Server umleitet. Dieser Endpunkt kann getted 或 posted。在这两种情况下,http 响应代码都应为 302。如果我在此代码上使用 curl ,它确实在两种情况下都显示响应代码 302,并且 curl -l sein, um Weiterleitungen korrekt zu folgen. Wow.

Aber

Meine Unit-Tests verwenden httptest.newrecorder()来捕获信息,但它仅适用于get,不适用于post。因此,当我知道实际的重定向正在工作时,我需要弄清楚如何让单元测试工作。失败测试显示http响应代码是200而不是302(http.statusfound).

$ go run foo.go
post code 200
get code 302
Nach dem Login kopieren

Dies ist ein unabhängiger Test.

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")
    }
}
Nach dem Login kopieren

Wenn ich Curl Post in der eigentlichen Anwendung ausführe (nicht gezeigt), sehe ich, dass es funktioniert:

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
Nach dem Login kopieren

Lösung

tl;dr

Die Lösung ist in context.redirect 之后显式调用 context.writer.writeheadernow.

Anleitung

Dies ist ein Randfall der Verwendung des von gin.createtestcontext zurückgegebenen Gin-Kontexts.

Bei Get-Anfragen ruft Gin schließlich http.redirect ,它将向响应写入一个简短的 html 正文(类似于 <a href="http://foobar.com">found</a> auf, wodurch der Statuscode der Antwort geschrieben wird.

Bei Post-Anfragen http.redirect wird der kurze HTML-Text nicht geschrieben und der Statuscode hat keine Chance, in die Antwort geschrieben zu werden.

Siehe Implementierung von http.redirect. Wenn der content-type-Header zuvor festgelegt wurde, tritt laut Quellcode das gleiche Problem mit der Get-Anfrage auf:

{
    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")
  }
Nach dem Login kopieren

Die Lösung besteht darin, explizit context.writer.writeheadernow:

aufzurufen
{
    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")
  }
Nach dem Login kopieren

gin selbst verwendet die gleiche Problemumgehung. Siehe testcontextrenderredirectwithrelativepath.

Eine echte Serveranwendung wird nicht unter dem gleichen Problem leiden wie (*engine).handlehttprequest 将为我们调用 writeheadernow (siehe Quellcode). Deshalb nenne ich es eher einen „Edge Case“ als einen „Bug“.

Das obige ist der detaillierte Inhalt vonUnit-Test für Gins Context.Redirect funktioniert für GET-Antwortcodes, aber nicht für POST-Antwortcodes (Golang). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage