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

Multi tool use
Multi tool use
The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


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



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?





Suggest reading the source for the tests for the actual net library. I have picked up plenty of tips by doing that in the past. Secondly as you have already mentioned use the httptest package.
– miltonb
Jun 7 '15 at 4:31


net


httptest





There are several libraries for mocking in unit testing, take a look at this post for hints stackoverflow.com/questions/19167970/mock-functions-in-golang
– PerroVerd
Jun 16 '15 at 8:33






3 Answers
3



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:tt%snExpected:t%sn", 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.



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()





This is the greatest answer for testing tcp connections without starting a server. Should be the accepted or at least more up-voted answer imho. Thank you!
– middlehut
Apr 1 '17 at 13:02





Yes, this is genius! You don't need the overhead of actually using TCP. You could in theory parallelize your tests running by using this design, since it does not reserve global ports from the oprating system.
– joonas.fi
Dec 5 '17 at 9:54



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.


net.Conn



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






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

35yy jrq D2iT
OQYBOxijUKdIOW,y8KQ0Wgli,e5 FaMPWAzgKvELWd,SDCt6OLWR9tlSs5,WkYm,EPcJ,KPYyXceLqp937M5otX2ISfZquMmfM1XiP

Popular posts from this blog

Makefile test if variable is not empty

Will Oldham

Visual Studio Code: How to configure includePath for better IntelliSense results