Home  >  Article  >  Backend Development  >  Golang: Intercept and simulate HTTP responses using httptest

Golang: Intercept and simulate HTTP responses using httptest

王林
王林forward
2024-02-09 08:24:331135browse

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

php editor Zimo brings you an article about using httptest to intercept and simulate HTTP responses in Golang. In this article, we will take a deep dive into how to use the httptest package to intercept HTTP requests and simulate responses for unit testing and functional testing. By using httptest, we can easily simulate HTTP responses in various scenarios to test the correctness and robustness of our code. Mastering these techniques is very useful for both beginners and experienced developers. Next, let’s learn about the specific implementation method!

Question content

I've looked into various different tools available for mock testing in golang, but I'm trying to use httptest to accomplish this task. In particular, I have a function like this:

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
}

A lot of the documentation I've read seems to require creating a client interface or a custom transport. Is there a way to simulate the response in a test file without changing this main code? I want to keep my client, response and all related details in the getresponse function. I may have the wrong idea but I'm trying to find a way to intercept the http.defaultclient.do(req) call and return a custom response, is this possible?

Solution

I have read that it seems that a client interface needs to be created

Do not change this main code at all

Keeping your code clean is a good practice, you will eventually get used to it, testable code is cleaner, and cleaner code is more testable, so don't worry about changing your code (using interfaces) so that it can Accepts a mock object.

The simplest form of code can be like this:

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
}

Your test could look like this:

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

But if you prefer to use 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)
}

The above is the detailed content of Golang: Intercept and simulate HTTP responses using httptest. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete