it-swarm.com.de

Wie testet man net.Conn in Unit-Tests in Golang?

Ich bin gerade dabei, einige Komponententests für die net.Conn-Benutzeroberfläche in Go sowie andere Funktionen zu erstellen, die auf diesen Funktionen aufbauen, und ich frage mich, wie ich diese in Google Go am besten testen kann. Mein Code sieht so aus:

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

Ist die effizienteste Methode zum Testen dieses Codes und des Codes, der diese Funktionen verwendet, um eine separate Goroutine zu starten, die sich wie der Server verhält, net.http.httptest package oder etwas anderes?

14
ThePiachu

Obwohl dies von den Implementierungsdetails Ihres speziellen Falls abhängt, besteht der allgemeine Ansatz darin, einen Server (in einer separaten Goroutine, wie Sie bereits angedeutet haben) zu starten und die eingehenden Verbindungen zu überwachen.

Lassen Sie uns zum Beispiel einen Server hochfahren und überprüfen, ob der Inhalt, den wir von der Verbindung lesen, tatsächlich derjenige ist, den wir vom Client senden:

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
    }

}

Beachten Sie, dass ich hier den Server nicht in der Goroutine starte, da der Test sonst wahrscheinlich beendet wird, bevor der Listener den Test ausgeführt hat.

8
Iñigo

Möglicherweise können Sie mit net.Pipe das tun, was Sie brauchen. Im Grunde bedeutet dies, dass Sie beide Enden einer Verbindung haben (denken Sie nach .Accept ()).

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

// Do some stuff
client.Close()
46
Freman

Eine weitere Option ist das Fälscher - Paket, mit dem Sie Mocks aus Schnittstellen erstellen und dann alle benötigten Aufrufe abarbeiten können. Ich habe es mit großem Erfolg verwendet, um net.Conn-Instanzen auszusondern, in denen ich einen protobuf-Client für Geode teste.

Zum Beispiel - https://github.com/gemfire/geode-go-client/blob/master/connector/protobuf_test.go

0
Jens D