Maison  >  Article  >  développement back-end  >  Golang : interceptez et simulez les réponses HTTP à l'aide de httptest

Golang : interceptez et simulez les réponses HTTP à l'aide de httptest

王林
王林avant
2024-02-09 08:24:331135parcourir

Golang:使用 httptest 拦截和模拟 HTTP 响应

L'éditeur PHP Zimo vous propose un article sur l'utilisation de httptest pour intercepter et simuler les réponses HTTP dans Golang. Dans cet article, nous examinerons en profondeur comment utiliser le package httptest pour intercepter les requêtes HTTP et simuler les réponses pour les tests unitaires et fonctionnels. En utilisant httptest, nous pouvons facilement simuler des réponses HTTP dans divers scénarios pour tester l'exactitude et la robustesse de notre code. La maîtrise de ces techniques est très utile aussi bien pour les développeurs débutants que confirmés. Découvrons ensuite la méthode de mise en œuvre spécifique !

Contenu de la question

J'ai examiné différents outils disponibles pour des tests simulés dans Golang, mais j'essaie d'utiliser httptest pour accomplir cette tâche. J'ai notamment une fonction comme celle-ci :

type contact struct {
  username string
  number int
}

func getResponse(c contact) string {
  url := fmt.Sprintf("https://mywebsite/%s", c.username)
  req, err := http.NewRequest(http.MethodGet, url, nil)
  // error checking
 
  resp, err := http.DefaultClient.Do(req)
  // error checking
  
  return response
}

Une grande partie de la documentation que j'ai lue semble nécessiter la création d'une interface client ou d'un transport personnalisé. Existe-t-il un moyen de simuler la réponse dans un fichier de test sans modifier ce code principal ? Je souhaite conserver mon client, sa réponse et tous les détails associés dans l'appel getresponse 函数中。我可能有错误的想法,但我正在尝试找到一种方法来拦截 http.defaultclient.do(req) et renvoyer une réponse personnalisée, est-ce possible ?

Solution de contournement

J'ai lu qu'il semble que vous deviez créer une interface client

Ne changez pas du tout ce code principal

Garder votre code propre est une bonne pratique, vous finirez par vous y habituer, le code testable est plus propre et le code plus propre est plus testable, alors ne vous inquiétez pas de changer votre code (à l'aide d'interfaces) pour qu'il puisse accepter les objets simulés .

La forme de code la plus simple peut ressembler à ceci :

package main

import (
    "fmt"
    "net/http"
)

type contact struct {
    username string
    number   int
}

type client interface {
    do(req *http.request) (*http.response, error)
}

func main() {
    getresponse(http.defaultclient, contact{})
}

func getresponse(client client, c contact) string {
  url := fmt.sprintf("https://mywebsite/%s", c.username)
  req, _ := http.newrequest(http.methodget, url, nil)
  // error checking

  resp, _ := http.defaultclient.do(req)
  // error checking and response processing

  return response
}

Votre test pourrait ressembler à ceci :

package main

import (
    "net/http"
    "testing"
)

type mockclient struct {
}

// do function will cause mockclient to implement the client interface
func (tc mockclient) do(req *http.request) (*http.response, error) {
    return &http.response{}, nil
}

func testgetresponse(t *testing.t) {
    client := new(mockclient)
    getresponse(client, contact{})
}

Mais si vous préférez utiliser httptest :

package main

import (
    "fmt"
    "io"
    "net/http"
    "net/http/httptest"
)

type contact struct {
    username string
    number   int
}

func main() {
    fmt.Println(getResponse(contact{}))
}

func getResponse(c contact) string {
    // Make a test server
    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "your response")
    }))

    defer ts.Close()

    // You should still set your base url
    base_url := ts.URL

    url := fmt.Sprintf("%s/%s", base_url, c.username)
    req, _ := http.NewRequest(http.MethodGet, url, nil)

    // Use ts.Client() instead of http.DefaultClient in your tests.
    resp, _ := ts.Client().Do(req)

    // Processing the response
    response, _ := io.ReadAll(resp.Body)
    resp.Body.Close()

    return string(response)
}

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