如何在golang中为http请求编写单元测试?

Utk*_*thi 2 unit-testing http go

我不知道如何测试下面代码中给出的 http 响应。

func getVolDetails(volName string, obj interface{}) error {
    addr := os.Getenv("MAPI_ADDR")
    if addr == "" {
        err := errors.New("MAPI_ADDR environment variable not set")
        fmt.Println(err)
        return err
    }
    url := addr + "/path/to/somepage/" + volName
    client := &http.Client{
        Timeout: timeout,
    }
    resp, err := client.Get(url)
    if resp != nil {
        if resp.StatusCode == 500 {
            fmt.Printf("VSM %s not found\n", volName)
            return err
        } else if resp.StatusCode == 503 {
            fmt.Println("server not reachable")
            return err
        }
    } else {
        fmt.Println("server not reachable")
        return err
    }

    if err != nil {
        fmt.Println(err)
        return err
    }
    defer resp.Body.Close()

    return json.NewDecoder(resp.Body).Decode(obj)
}
Run Code Online (Sandbox Code Playgroud)

在一些参考资料的帮助下,我为此编写了单元测试,如下所示

func TestGetVolDetails(t *testing.T) {
    var (
        volume v1.Volume
        server *httptest.Server
    )
    tests := map[string]struct {
        volumeName string
        err        error
    }{
        "TestOne": {"vol", nil},
    }
    for name, tt := range tests {
        t.Run(name, func(t *testing.T) {
            response := `{"metadata":{"annotations":{"vsm.openebs.io/targetportals":"10.98.65.136:3260","vsm.openebs.io/cluster-i    ps":"10.98.65.136","openebs.io/jiva-iqn":"iqn.2016-09.com.openebs.jiva:vol","deployment.kubernetes.io/revision":"1","openebs.io/storage-pool"    :"default","vsm.openebs.io/replica-count":"1","openebs.io/jiva-controller-status":"Running","openebs.io/volume-monitor":"false","openebs.io/r    eplica-container-status":"Running","openebs.io/jiva-controller-cluster-ip":"10.98.65.136","openebs.io/jiva-replica-status":"Running","vsm.ope    nebs.io/iqn":"iqn.2016-09.com.openebs.jiva:vol","openebs.io/capacity":"2G","openebs.io/jiva-controller-ips":"10.36.0.6","openebs.io/jiva-repl    ica-ips":"10.36.0.7","vsm.openebs.io/replica-status":"Running","vsm.openebs.io/controller-status":"Running","openebs.io/controller-container-    status":"Running","vsm.openebs.io/replica-ips":"10.36.0.7","openebs.io/jiva-target-portal":"10.98.65.136:3260","openebs.io/volume-type":"jiva    ","openebs.io/jiva-replica-count":"1","vsm.openebs.io/volume-size":"2G","vsm.openebs.io/controller-ips":"10.36.0.6"},"creationTimestamp":null    ,"labels":{},"name":"vol"},"status":{"Message":"","Phase":"Running","Reason":""}}`
            server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                fmt.Fprintln(w, response)
            }))
            os.Setenv("MAPI_ADDR", "http://"+server.URL)
            if got := GetVolDetails(tt.volumeName, &volume); got != tt.err {
                t.Fatalf("GetVolDetails(%v) => got %v, want %v ", tt.volumeName, got, tt.err)
            }
            defer server.Close()
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

其中 response 是我从服务器得到的响应。这给了我总是不同的错误。 got invalid character '<' looking for beginning of value, want <nil>

got Get http://www.HugeDomains.com: net/http: request canceled (Client.Timeout exceeded while awaiting headers), want <nil>

我究竟做错了什么?

编辑:

使用 SOME_ADDR 将代码更新为 MAPI_ADDR,这是在发布问题时完成的。请不要与此混淆,问题仍然存在。

Iai*_*can 10

您收到超时,但没有指定timeout设置的内容。我怀疑这不是 time.Duration 对象,这导致您超时。还有一些其他问题。为了让它工作,我做了:

  1. 将测试中调用的函数更改getVolDetails为匹配代码(不是小写g
  2. Timeout创建时设置clientTimeout: time.Second * 10
  3. "http://"+os.Setenv("MAPI_ADDR", "http://"+server.URL)行中删除

更正后的代码是:

var timeout time.Duration = time.Second * 1000

func getVolDetails(volName string, obj interface{}) error {
    addr := os.Getenv("MAPI_ADDR")
    if addr == "" {
        err := errors.New("MAPI_ADDR environment variable not set")
        fmt.Println(err)
        return err
    }
    url := addr + "/path/to/somepage/" + volName
    client := &http.Client{
        Timeout: timeout,
    }
    resp, err := client.Get(url)
    if resp != nil {
        if resp.StatusCode == 500 {
            fmt.Printf("VSM %s not found\n", volName)
            return err
        } else if resp.StatusCode == 503 {
            fmt.Println("server not reachable")
            return err
        }
    } else {
        fmt.Println("server not reachable")
        return err
    }

    if err != nil {
        fmt.Println(err)
        return err
    }
    defer resp.Body.Close()

    return json.NewDecoder(resp.Body).Decode(obj)
}
Run Code Online (Sandbox Code Playgroud)

并测试:

func TestGetVolDetails(t *testing.T) {
    var (
        volume v1.Volume
        server *httptest.Server
    )
    tests := map[string]struct {
        volumeName string
        err        error
    }{
        "TestOne": {"vol", nil},
    }
    for name, tt := range tests {
        t.Run(name, func(t *testing.T) {
            response := `{"metadata":{"annotations":{"vsm.openebs.io/targetportals":"10.98.65.136:3260","vsm.openebs.io/cluster-i    ps":"10.98.65.136","openebs.io/jiva-iqn":"iqn.2016-09.com.openebs.jiva:vol","deployment.kubernetes.io/revision":"1","openebs.io/storage-pool"    :"default","vsm.openebs.io/replica-count":"1","openebs.io/jiva-controller-status":"Running","openebs.io/volume-monitor":"false","openebs.io/r    eplica-container-status":"Running","openebs.io/jiva-controller-cluster-ip":"10.98.65.136","openebs.io/jiva-replica-status":"Running","vsm.ope    nebs.io/iqn":"iqn.2016-09.com.openebs.jiva:vol","openebs.io/capacity":"2G","openebs.io/jiva-controller-ips":"10.36.0.6","openebs.io/jiva-repl    ica-ips":"10.36.0.7","vsm.openebs.io/replica-status":"Running","vsm.openebs.io/controller-status":"Running","openebs.io/controller-container-    status":"Running","vsm.openebs.io/replica-ips":"10.36.0.7","openebs.io/jiva-target-portal":"10.98.65.136:3260","openebs.io/volume-type":"jiva    ","openebs.io/jiva-replica-count":"1","vsm.openebs.io/volume-size":"2G","vsm.openebs.io/controller-ips":"10.36.0.6"},"creationTimestamp":null    ,"labels":{},"name":"vol"},"status":{"Message":"","Phase":"Running","Reason":""}}`
            server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                fmt.Fprintln(w, response)
            }))
            os.Setenv("MAPI_ADDR", server.URL)
            if got := getVolDetails(tt.volumeName, &volume); got != tt.err {
                t.Fatalf("GetVolDetails(%v) => got %v, want %v ", tt.volumeName, got, tt.err)
            }
            defer server.Close()
        })
    }
}
Run Code Online (Sandbox Code Playgroud)