为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
白猪掌柜的 2023-05-15 15:35:07
我有以下按预期工作的功能。现在我想为它运行一个单元测试。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,        },    }
查看完整描述

2 回答

?
慕工程0101907

TA贡献1887条经验 获得超5个赞

我建议看一下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)

  }

}


查看完整回答
反对 回复 2023-05-15
?
墨色风雨

TA贡献1853条经验 获得超6个赞

我会使用类似以下代码的东西。用法是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 array

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


查看完整回答
反对 回复 2023-05-15
  • 2 回答
  • 0 关注
  • 107 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信