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

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

WBOY
WBOYnach vorne
2024-02-10 19:27:081201Durchsuche

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

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")
    }
}

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

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 正文(类似于 64ac7c208db62edaa9346a44958f6a3efound5db79b134e9f6b82c0b36e0489ee08ed 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")
  }

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")
  }

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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen