亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何對修改發送消息的 net.Conn 函數進行單元測試?

如何對修改發送消息的 net.Conn 函數進行單元測試?

Go
森欄 2022-10-10 15:49:25
首先,讓我告訴我,我已經看到了與這個類似的其他問題,但我認為沒有一個問題能真正詳細地回答它(How do one test net.Conn in unit tests in Golang?和How does Golang 單元測試中的一個測試 net.Conn?)。我要測試的是以某種方式響應 TCP 請求的功能。在最簡單的情況下:func HandleMessage(c net.Conn) {  s, err := bufio.NewReader(c).ReadString('\n')  s = strings.Trim(s, "\n")  c.Write([]byte(s + " whatever"))}我將如何對這樣的功能進行單元測試,理想情況下使用net.Pipe()不打開實際連接。我一直在嘗試這樣的事情:func TestHandleMessage(t *testing.T) {  server, client := net.Pipe()  go func(){    server.Write([]byte("test"))    server.Close()  }()  s, err := bufio.NewReader(c).ReadString('\n')  assert.Nil(t, err)  assert.Equal(t, "test whatever", s) }但是我似乎無法理解在哪里放置HandleMessage(client)(或HandleMessage(server)?在測試中實際獲得我想要的響應。我可以讓它阻塞并且根本不會完成,或者它將返回我在服務器中編寫的完全相同的字符串。有人可以幫助我并指出我在哪里犯了錯誤嗎?或者在測試 TCP 功能時可能指向正確的方向。
查看完整描述

2 回答

?
一只萌萌小番薯

TA貢獻1795條經驗 獲得超7個贊

net.Pipe 文檔說:

Pipe 創建一個同步的、內存中的、全雙工的網絡連接;兩端都實現了 Conn 接口。一端的讀取與另一端的寫入匹配,直接在兩者之間復制數據;沒有內部緩沖。

因此,您附加到net.Conn's (serverclient) 的標簽是任意的。如果您發現它更容易理解,請隨意使用 something line handleMessageConn, sendMessageConn := net.Pipe()。

下面基本上填寫了您提到的答案中給出的示例。

func TestHandleMessage(t *testing.T) {

    server, client := net.Pipe()


    // Set deadline so test can detect if HandleMessage does not return

    client.SetDeadline(time.Now().Add(time.Second))


    // Configure a go routine to act as the server

    go func() {

        HandleMessage(server)

        server.Close()

    }()



    _, err := client.Write([]byte("test\n"))

    if err != nil {

        t.Fatalf("failed to write: %s", err)

    }


    // As the go routine closes the connection ReadAll is a simple way to get the response

    in, err := io.ReadAll(client)

    if err != nil {

        t.Fatalf("failed to read: %s", err)

    }


    // Using an Assert here will also work (if using a library that provides that functionality)

    if string(in) != "test whatever" {

        t.Fatalf("expected `test` got `%s`", in)

    }


    client.Close()

}

您可以扭轉這種情況并將Write/Read放在 go 例程中,但我相信上述方法更容易理解并簡化了避免測試包的限制:


測試在其 Test 函數返回或調用任何方法 FailNow、Fatal、Fatalf、SkipNow、Skip 或 Skipf 時結束。這些方法以及 Parallel 方法只能從運行 Test 函數的 goroutine 中調用。


注意:如果您不需要net.Conn(就像這個簡單示例中的情況),請考慮使用HandleMessage(c io.ReadWriter)(這為用戶提供了更大的靈活性并簡化了測試)。


查看完整回答
反對 回復 2022-10-10
?
收到一只叮咚

TA貢獻1821條經驗 獲得超5個贊

塊并且根本不會完成


好吧,您發布的代碼是如此不完整,以至于我無法知道這些是否是您面臨的真正問題-例如,沒有c. TestHandleMessage但是給你懷疑的好處,我會說這段代碼有兩個問題:


首先,您的測試從不寫入,client因此沒有可讀取的內容server。您寫入server并關閉它,但您從不向client. 所以這是第一個問題,但同樣,該代碼不會編譯。


其次,看這個組合:


  c.Write([]byte(s + " whatever"))

  s, err := bufio.NewReader(c).ReadString('\n')

HandleMessage不寫換行符,但客戶需要一個。它無限期地掛起,等待永遠不會被寫入的換行符。同樣,我不確定您是否遇到了這個問題或第一個問題或兩者兼而有之 - 因為您的代碼無法編譯。


您必須更改此行:


  c.Write([]byte(s + " whatever\n"))

您還必須將初始字符串寫入客戶端連接,以便管道另一端可以讀取它server。


將它們放在一起,提取任何外部依賴項(作證),并修復一些錯誤最終得到:


t.go:


package main


import (

    "net"

    "fmt"

    "bufio"

    "strings"

)


func HandleMessage(c net.Conn) {

  s, err := bufio.NewReader(c).ReadString('\n')

    if err != nil {

        panic(fmt.Errorf("HandleMessage could not read: %w", err))

    }

  s = strings.Trim(s, "\n")

  c.Write([]byte(s + " whatever\n"))

}

t_test.go:


package main


import(

    "net"

    "bufio"

    "fmt"

    "testing"

)


func TestHandleMessage(t *testing.T) {

  server, client := net.Pipe()


  go func(){

    HandleMessage(server)

  }()

    fmt.Fprintln(client, "test")

  s, err := bufio.NewReader(client).ReadString('\n')


  if err != nil {

        t.Errorf("Error should be nil, got: %s", err.Error())

    }

    if s != "test whatever\n" {

        t.Errorf("Expected result to be 'test whatever\\n', got %s", s)

    }

}

% go test t.go t_test.go -v

=== RUN   TestHandleMessage

--- PASS: TestHandleMessage (0.00s)

PASS

ok      command-line-arguments  0.100s


查看完整回答
反對 回復 2022-10-10
  • 2 回答
  • 0 關注
  • 111 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號