-
Notifications
You must be signed in to change notification settings - Fork 221
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
936 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,84 @@ | ||
# 8.3 测试技巧:网络测试 | ||
|
||
### 1. TCP/HTTP | ||
|
||
假设需要测试某个 API 接口的 handler 能够正常工作,例如 helloHandler | ||
|
||
``` go | ||
func helloHandler(w http.ResponseWriter, r *http.Request) { | ||
w.Write([]byte("hello world")) | ||
} | ||
``` | ||
|
||
那我们可以创建真实的网络连接进行测试: | ||
|
||
```go | ||
// 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` 进行测试更为高效。 | ||
|
||
上述的测试用例改写如下: | ||
|
||
```go | ||
// 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),达到了相同的目的。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,90 @@ | ||
8.3 测试技巧:网络测试 | ||
====================== | ||
|
||
1. TCP/HTTP | ||
~~~~~~~~~~~ | ||
|
||
假设需要测试某个 API 接口的 handler 能够正常工作,例如 helloHandler | ||
|
||
.. code:: go | ||
|
||
func helloHandler(w http.ResponseWriter, r *http.Request) { | ||
w.Write([]byte("hello world")) | ||
} | ||
那我们可以创建真实的网络连接进行测试: | ||
|
||
.. code:: go | ||
// 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`` | ||
进行测试更为高效。 | ||
|
||
上述的测试用例改写如下: | ||
|
||
.. code:: go | ||
// 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),达到了相同的目的。 |
Oops, something went wrong.