测试技巧:网络测试
1. TCP/HTTP
假设需要测试某个 API 接口的 handler 能够正常工作,例如 helloHandler
func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("hello world"))
}
那我们可以创建真实的网络连接进行测试:
// test code
import (
    "io/ioutil"
    "net"
    "net/http"
    "testing"
)
func handleError(t *testing.T, err error) {
    t.Helper()
    if err != nil {
        t.Fatal("failed", err)
    }
}
func TestConn(t *testing.T) {
    ln, err := net.Listen("tcp", "127.0.0.1:0")
    handleError(t, err)
    defer ln.Close()
    http.HandleFunc("/hello", helloHandler)
    go http.Serve(ln, nil)
    resp, err := http.Get("http://" + ln.Addr().String() + "/hello")
    handleError(t, err)
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    handleError(t, err)
    if string(body) != "hello world" {
        t.Fatal("expected hello world, but got", string(body))
    }
}
net.Listen("tcp", "127.0.0.1:0"):监听一个未被占用的端口,并返回 Listener。- 调用 
http.Serve(ln, nil)启动 http 服务。 - 使用 
http.Get发起一个 Get 请求,检查返回值是否正确。 - 尽量不对 
http和net库使用 mock,这样可以覆盖较为真实的场景。 
2. httptest
针对 http 开发的场景,使用标准库 net/http/httptest 进行测试更为高效。
上述的测试用例改写如下:
// test code
import (
    "io/ioutil"
    "net/http"
    "net/http/httptest"
    "testing"
)
func TestConn(t *testing.T) {
    req := httptest.NewRequest("GET", "http://example.com/foo", nil)
    w := httptest.NewRecorder()
    helloHandler(w, req)
    bytes, _ := ioutil.ReadAll(w.Result().Body)
    if string(bytes) != "hello world" {
        t.Fatal("expected hello world, but got", string(bytes))
    }
}
使用 httptest 模拟请求对象(req)和响应对象(w),达到了相同的目的。
END 链接
✴️版权声明 © :本书所有内容遵循CC-BY-SA 3.0协议(署名-相同方式共享)©