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

时间:2018-01-12 14:24:30

标签: 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)
}

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

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

响应是我从服务器获得的响应。这给了我不同的错误。 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,这是在发布问题时完成的。请不要对此感到困惑,问题仍然存在。

1 个答案:

答案 0 :(得分:3)

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

  1. 将测试中调用的函数更改为getVolDetails以匹配代码(不是小写g
  2. 在创建Timeoutclient
  3. 时设置Timeout: time.Second * 10
  4. "http://"+
  5. 中删除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)
    }
    

    并测试:

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