Как проходит тестирование net.Conn в модульных тестах в Голанге?

В настоящее время я изучаю некоторые модульные тесты для интерфейса net.Conn в Go, а также другие функции, которые создаются поверх этой функциональности, и мне интересно, что является лучшим способом для unit test, что в Google Go? Мой код выглядит так:

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

Является наиболее эффективным способом тестирования этого кода и кода, который использует эти функции, чтобы развернуть отдельный goroutine, чтобы действовать как сервер, используйте net.http.httptest или что-то еще?

Ответ 1

Хотя это будет зависеть от деталей реализации вашего конкретного случая, общим подходом будет запуск сервера (в отдельной версии 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
    }

}

Обратите внимание, что здесь я не запускаю сервер в goroutine, так как в противном случае тестовый пример, вероятно, будет завершен до того, как слушатель выполнит тест.

Ответ 2

Возможно, вы сможете сделать то, что вам нужно, net.Pipe, который в основном дает вам оба конца соединения (подумайте, после.())

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

// Do some stuff
client.Close()