Maison  >  Article  >  développement back-end  >  Le test unitaire pour Context.Redirect de gin fonctionne pour les codes de réponse GET mais pas pour les codes de réponse POST (golang)

Le test unitaire pour Context.Redirect de gin fonctionne pour les codes de réponse GET mais pas pour les codes de réponse POST (golang)

WBOY
WBOYavant
2024-02-10 19:27:081124parcourir

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

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.

Contenu de la question

Je souhaite que mon serveur redirige un point de terminaison spécifique vers un autre serveur. Ce point de terminaison peut être getted 或 posted。在这两种情况下,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

Solution

tl;dr

La solution est en context.redirect 之后显式调用 context.writer.writeheadernow.

Instructions

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

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer