Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
144 lines (112 sloc) 3.38 KB

测试 HTTP handler

在这节我们将学习如果用 Go 测试 HTTP handlers,这是一个用 Go 测试的特别例子。我们将已 www.go 的代码为基础,修改需要调整的地方。

新版本的 www.go 命名为 testWWW.go,并分为三部分展示。testWWW.go 的第一部分代码如下:

package main

import (
    "fmt"
    "net/http"
    "os"
)

func CheckStatusOK(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, `Fine!`)
}

testWWW.go 的第二部分代码如下:

func StatusNotFound(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
    fmt.Printf("Served: %s\n", r.Host)
}

func MyHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
    fmt.Printf("Served: %s\n", r.Host)
}

testWWW.go 余下代码如下:

func main() {
    PORT := ":8001"
    arguments := os.Args
    if len(arguments) == 1 {
        fmt.Println("Using default port number:", PORT)
    } else {
        PORT = ":" + arguments[1]
    }

    http.HandleFunc("/CheckStatusOK", CheckStatusOK)
    http.HandleFunc("/StatusNotFound", StatusNotFound)
    http.HandleFunc("/", MyHandler)

    err := http.ListenAndServe(PORT, nil)
    if err != nil {
        fmt.Println(err)
        return
    }
}

我们现在需要开始测试 testWWW.go 了,为此我们应该创建一个 testWWW_test.go 文件。这个文件的内容由四部分展示。

testWWW_test.go 的第一部分包容如下代码:

package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
    "testing"
)

注意,为了用 Go 测试 web 应用,您需要引入 net/http/httptest 标准包。

testWWW_tesst.go 的第二部分如下:

func TestCheckStatusOK(t *testing.T) {
    req, err := http.NewRequest("GET", "/CheckStatusOK", nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    rr := httptest.NewRecorder()
    handler := http.HandlerFunc(CheckStatusOK)
    handler.ServeHTTP(rr, req)

httptest.NewRecorder() 函数返回一个 httptest.ResponseRecorder 对象,它被用于记录 HTTP 响应。

testWWW_test.go 的第三部分如下:

    status := rr.Code
    if status != http.StatusOK {
        t.Errorf("handler returned %v", status)
    }

    expect := `Fine!`
    if rr.Body.String() != expect {
        t.Errorf("handler returned %v", rr.Body.String())
    }
}

您首先检查返回码是所期望的,然后再验证返回消息体也是您期望的。

testWWW_test.go 的余下代码如下:

func TestStatusNotFound(t *testing.T) {
    req, err := http.NewRequest("GET", "/StatusNotFound", nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    rr := httptest.NewRecorder()
    handler := http.HandlerFunc(StatusNotFound)
    handler.ServeHTTP(rr, req)

    status := rr.Code
    if status != http.StatusNotFound {
        t.Errorf("handler returned %v", status)
    }
}

这个测试函数验证 main 包中的 StatusNotFound() 函数是否如期运行。

执行 testWWW_test.go 的这俩个测试函数将产生如下输出:

$ go test testWWW.go testWWW_test.go -v
=== RUN     TestCheckStatusOK
--- PASS:   TestCheckStatusOK (0.00s)
=== RUN     TestStatusNotFound
--- PASS:   TestStatusNotFound (0.00s)
PASS
ok      command-line-arguments  (cached)
You can’t perform that action at this time.