Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 273
ThePiachu Avatar asked Jun 06 '15 23:06

ThePiachu


People also ask

How do you test concurrency in go?

If you want to test concurrency you'll need to make a few go routines and have them run, well, concurrently. You might try taking the locking out and intentionally get it to crash or misbehave by concurrently modifying things and then add the locking in to ensure it solves it.

How do I run a test case in Golang?

At the command line in the greetings directory, run the go test command to execute the test. The go test command executes test functions (whose names begin with Test ) in test files (whose names end with _test.go). You can add the -v flag to get verbose output that lists all of the tests and their results.


2 Answers

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() 
like image 88
Freman Avatar answered Oct 03 '22 01:10

Freman


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.

like image 20
Iñigo Avatar answered Oct 03 '22 00:10

Iñigo