How does one test net.Conn in unit tests in Golang?

19,396

Solution 1

Although it will depend on the implementation details of your particular case, the general approach will be to start a server (in a separate goroutine, as you already hinted), and listen to the incoming connections.

For example, let's spin up a server and verify that the content we are reading from the connection is indeed the one we send over from the client:

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
    }

}

Note that here I'm not starting the server in the goroutine, as otherwise the test case is likely to be finished before the listener has run the test.

Solution 2

You might be able to do what you need with net.Pipe which basically gives you both ends of a connection (think, after .Accept())

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

// Do some stuff
client.Close()

Solution 3

Another option is the counterfeiter package which lets you create mocks from interfaces and then you can stub out whatever calls you need. I have used it with great success to stub out net.Conn instances where I am testing out a protobuf client for Geode.

For example - https://github.com/gemfire/geode-go-client/blob/master/connector/protobuf_test.go

Share:
19,396
ThePiachu
Author by

ThePiachu

Computer Science double BSc, master-level student. Bitcoin enthusiast. My Google-powered Bitcoin Calculator: http://tpbitcalc.appspot.com/ My tweets: http://twitter.com/#!/ThePiachu If you have an iPhone and need some dice, check out my apps: http://tiny.cc/TPiDev

Updated on June 05, 2022

Comments

  • ThePiachu
    ThePiachu almost 2 years

    I'm currently looking into creating some unit tests for net.Conn interface in Go, as well as other functions that build up on top of that functionality, and I'm wondering what is the best way to unit test that in Google Go? My code looks like:

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

    Is the most efficient way of testing this code and the code that uses these functions to spin up a separate goroutine to act like the server, use net.http.httptest package, or something else?