Tom*_*ski 2 testing unit-testing tcp go
首先,让我告诉我,我见过与此类似的其他问题,但我认为没有任何问题真正足够详细地回答它(How does one test net.Conn in unit test in Golang?和How does Golang 单元测试中的一个测试 net.Conn?)。
我想测试的是以某种方式响应 TCP 请求的函数。
在最简单的场景中:
func HandleMessage(c net.Conn) {
s, err := bufio.NewReader(c).ReadString('\n')
s = strings.Trim(s, "\n")
c.Write([]byte(s + " whatever"))
}
Run Code Online (Sandbox Code Playgroud)
我将如何对这样的功能进行单元测试,最好使用net.Pipe()不打开实际连接。我一直在尝试这样的事情:
func TestHandleMessage(t *testing.T) {
server, client := net.Pipe()
go func(){
server.Write([]byte("test"))
server.Close()
}()
s, err := bufio.NewReader(c).ReadString('\n')
assert.Nil(t, err)
assert.Equal(t, "test whatever", s)
}
Run Code Online (Sandbox Code Playgroud)
然而,我似乎无法理解将HandleMessage(client)( 或HandleMessage(server)?在测试中实际得到我想要的响应。我可以让它要么阻塞并且根本不会完成,要么它将返回与我在服务器中写入的字符串完全相同。
有人可以帮助我并指出我在哪里犯了错误吗?或者在测试 TCP 功能时指出正确的方向。
文档net.Pipe 说:
Pipe创建一个同步的、内存中的、全双工的网络连接;两端都实现Conn接口。一端的读取与另一端的写入相匹配,直接在两者之间复制数据;没有内部缓冲。
net.Conn因此,您附加到 的(server和)的标签client是任意的。如果您发现它更容易理解,请随意使用某些 line handleMessageConn, sendMessageConn := net.Pipe()。
下面基本上填写了您提到的答案中给出的示例。
func TestHandleMessage(t *testing.T) {
server, client := net.Pipe()
// Set deadline so test can detect if HandleMessage does not return
client.SetDeadline(time.Now().Add(time.Second))
// Configure a go routine to act as the server
go func() {
HandleMessage(server)
server.Close()
}()
_, err := client.Write([]byte("test\n"))
if err != nil {
t.Fatalf("failed to write: %s", err)
}
// As the go routine closes the connection ReadAll is a simple way to get the response
in, err := io.ReadAll(client)
if err != nil {
t.Fatalf("failed to read: %s", err)
}
// Using an Assert here will also work (if using a library that provides that functionality)
if string(in) != "test whatever" {
t.Fatalf("expected `test` got `%s`", in)
}
client.Close()
}
Run Code Online (Sandbox Code Playgroud)
您可以扭转这一局面并将Write/Read放入 go 例程中,但我相信上述方法更容易理解并简化避免测试包的限制:
当其 Test 函数返回或调用任何方法 FailNow、Fatal、Fatalf、SkipNow、Skip 或 Skipf 时,测试结束。这些方法以及 Parallel 方法只能从运行 Test 函数的 goroutine 中调用。
注意:如果您不需要net.Conn(如这个简单示例中的情况),请考虑使用HandleMessage(c io.ReadWriter)(这为用户提供了更大的灵活性,也简化了测试)。
| 归档时间: |
|
| 查看次数: |
1060 次 |
| 最近记录: |