如何使用 http 作为依赖项进行单元测试

我有以下按预期工作的功能。现在我想为它运行一个单元测试。


func httpClient(cc []string,method http) ([]byte, error) {

    httpClient := http.Client{}

    req, err := http.NewRequest(http.MethodPost, c[0]+"/oauth/token", nil)

    if err != nil {

        fmt.error(err)

    }

    //Here we are passing user and password

    req.SetBasicAuth(c[1], c[2])

    res, err := httpClient.Do(req)

    if err != nil {

        fmt.error(err)

    }

    val, err := ioutil.ReadAll(res.Body)

    if err != nil {

        fmt.error(err)

    }

    defer res.Body.Close()

    return val, nil

}

问题是我需要一些东西来伪造 http 调用,我尝试了以下方法,更改方法签名并将方法和 url 作为参数。问题是我不知道如何伪造该POST方法


这是更改后的代码,使测试更容易


func httpClient(cc []string, method string, url string) ([]byte, error) {

    httpClient := http.Client{}

    req, err := http.NewRequest(method, url, nil)

    if err != nil {

        return nil, errors.Wrap(err, "failed to execute http request")

    }

    //Here we are passing user and password

    req.SetBasicAuth(cc[1], cc[2])

    res, err := httpClient.Do(req)

    if err != nil {

        fmt.error(err)

    }

    val, err := ioutil.ReadAll(res.Body)

    if err != nil {

        fmt.error(err)

    }

    defer res.Body.Close()

    return val, nil

}

这是我尝试的测试,但仍然无法正常工作,因为我需要以某种方式伪造post 方法


func Test_httpClient(t *testing.T) {

    type args struct {

        params    []string

        method string

        url    string

    }

    tests := []struct {

        name    string

        args    args

        want    []byte

        wantErr bool

    }{

        {

            name:    "httpCallTest",

            args:{{"fakeuser", "fakepasswword"},{"post"},{"/any/url"}},

            want:    nil,

            wantErr: false,

        },


    }



白猪掌柜的
浏览 89回答 2
2回答

慕工程0101907

我建议看一下httptest包。它有一个非常适合您的假 HTTP 服务器。func Test_httpClient(t *testing.T){  var called bool  defer func(){    if !called{      t.Fatal("expected endpoint to be called")    }  }()  expectedValue = "some-value"  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){    called = true    u,p,ok := r.BasicAuth()    if !ok || u != "fakeuser" || p != "fakepassword" {      t.Fatal("wrong auth")    }    w.Write([]byte(expectedValue))  })  val, err := httpClient(   []string{"fakeuser", "fakepasswword"},    http.MethodPost,    server.URL,  )  if err != nil{    t.Fatal(err)  }  if val != expectedValue {    t.Fatalf("expected %q to equal %q", val, expectedValue)  }}

墨色风雨

我会使用类似以下代码的东西。用法是newTestServer(address).run()import (    "github.com/gorilla/mux"    "net/http"    "sync"    "time")type testServer struct {    addr   string    router *mux.Router}// addr can be e.g. `localhost:3030`// -> your client will do request on `localhost:3030/some/endpoint/path`func newTestServer(addr string) *testServer {    router := mux.NewRouter()    router.HandleFunc(        "/some/endpoint/path",        handleEndpoint,    ).Methods(http.MethodPost)    return &testServer{        addr:   addr,        router: router,    }}func handleEndpoint(writer http.ResponseWriter, request *http.Request) {    // your implementation}func (server *testServer) run() {    wg := sync.WaitGroup{}    wg.Add(1)    go func() {        wg.Done()        if err := http.ListenAndServe(server.addr, server.router); err != nil {            panic(err)        }    }()    wg.Wait()                          // wait for goroutine starts    time.Sleep(100 * time.Millisecond) // wait for listening starts}但我认为测试仍然不会通过。// this will panic// requires 2nd and 3rd item in an arrayreq.SetBasicAuth(cc[1], cc[2])
打开App,查看更多内容
随时随地看视频慕课网APP