如何在Golang的单元测试中测试net.Conn?

The*_*chu 19 testing unit-testing tcp go

我目前正在研究为Go中的net.Conn接口创建一些单元测试,以及在该功能之上构建的其他功能,我想知道在Google Go中进行单元测试的最佳方法是什么?我的代码看起来像:

conn, _:=net.Dial("tcp", "127.0.0.1:8080")
...
fmt.Fprintf(conn, "test")
...
buffer:=make([]byte, 100)
conn.Read(buffer)
Run Code Online (Sandbox Code Playgroud)

是测试此代码的最有效方法,以及使用这些函数来启动单独的goroutine以充当服务器的代码,使用net.http.httptest包,还是其他什么?

小智 72

你可能能够用net.Pipe做你需要的东西,它基本上给你连接的两端(想想,在.Accept()之后)

server, client := net.Pipe()
go func() {
  // Do some stuff
  server.Close()
}()

// Do some stuff
client.Close()
Run Code Online (Sandbox Code Playgroud)

  • 这是在不启动服务器的情况下测试TCP连接的最佳答案.应该是接受或至少更多的投票回答imho.谢谢! (9认同)
  • 您还可以查看“google.golang.org/grpc/test/bufconn” - 它在 net.Dialer 中实现内存中的 net.Listener,其中连接是“管道”,但与 net.Pipe 不同的是,它们也被缓冲,这使得它们在某些情况下更容易使用。 (3认同)
  • 能否请您举一个示例,说明如何使用此方法在此示例中测试WebSocket连接(大猩猩)。 (2认同)

Iñi*_*igo 11

虽然它将取决于您的特定情况的实现细节,但一般的方法是启动服务器(在您已经暗示的单独的goroutine中),并监听传入的连接.

例如,让我们启动服务器并验证我们从连接中读取的内容确实是我们从客户端发送的内容:

func TestConn(t *testing.T) {
    message := "Hi there!\n"

    go func() {
        conn, err := net.Dial("tcp", ":3000")
        if err != nil {
            t.Fatal(err)
        }
        defer conn.Close()

        if _, err := fmt.Fprintf(conn, message); err != nil {
            t.Fatal(err)
        }
    }()

    l, err := net.Listen("tcp", ":3000")
    if err != nil {
        t.Fatal(err)
    }
    defer l.Close()
    for {
        conn, err := l.Accept()
        if err != nil {
            return
        }
        defer conn.Close()

        buf, err := ioutil.ReadAll(conn)
        if err != nil {
            t.Fatal(err)
        }

        fmt.Println(string(buf[:]))
        if msg := string(buf[:]); msg != message {
            t.Fatalf("Unexpected message:\nGot:\t\t%s\nExpected:\t%s\n", msg, message)
        }
        return // Done
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,这里我没有在goroutine中启动服务器,否则测试用例很可能在侦听器运行测试之前完成.