Lors de l'écriture d'applications Web en langage Go, nous utilisons souvent le framework gin pour gérer les requêtes et les réponses HTTP. Lors de l'exécution de tests unitaires, nous devons effectuer des tests de couverture sur le code pour garantir la qualité et la stabilité du code. Cependant, le test unitaire pour la méthode Context.Redirect de gin fonctionne très bien lors du traitement des requêtes GET, mais pas aussi bien lors du traitement des requêtes POST. Dans cet article, l'éditeur PHP Apple expliquera en détail pourquoi ce problème se produit et fournira quelques solutions aux requêtes POST de tests unitaires.
Je souhaite que mon serveur redirige un point de terminaison spécifique vers un autre serveur. Ce point de terminaison peut être get
ted 或 post
ed。在这两种情况下,http 响应代码都应为 302。如果我在此代码上使用 curl
,它确实在两种情况下都显示响应代码 302,并且 curl -l
pour suivre correctement les redirections. Ouah.
Mais
Mes tests unitaires utilisent httptest.newrecorder()
来捕获信息,但它仅适用于get
,不适用于post
。因此,当我知道实际的重定向正在工作时,我需要弄清楚如何让单元测试工作。失败测试显示http响应代码是200而不是302(http.statusfound
).
$ go run foo.go post code 200 get code 302
Il s'agit d'un test indépendant.
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") } }
Lorsque j'exécute curl post sur l'application réelle (non affichée), je vois qu'elle fonctionne :
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
La solution est en context.redirect
之后显式调用 context.writer.writeheadernow
.
Il s'agit d'un cas limite d'utilisation du contexte gin renvoyé par gin.createtestcontext
.
Pour les demandes get, gin finira par appeler http.redirect
,它将向响应写入一个简短的 html 正文(类似于 <a href="http://foobar.com">found</a>
), provoquant l'écriture du code d'état de la réponse.
Pour les demandes de publication, http.redirect
le corps HTML court n'est pas écrit et le code d'état n'a aucune chance d'être écrit dans la réponse.
Voir implémentation de http.redirect. Selon le code source, si l'en-tête content-type
a été défini auparavant, le même problème se produira avec la requête 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") }
La solution est d'appeler explicitement 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 lui-même utilise la même solution de contournement. Voir testcontextrenderredirectwithrelativepath.
Une vraie application serveur ne souffrira pas du même problème que (*engine).handlehttprequest
将为我们调用 writeheadernow
(voir code source). C'est pourquoi j'appelle cela un « cas limite » plutôt qu'un « bug ».
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!