片状单元测试中的“连接被拒绝”错误,涉及启动 HTTP 服务器并连接到它

我正在尝试调试一个类似于以下内容的片状单元测试:


package main


import (

    "net"

    "net/http"

    "testing"

    "time"


    "github.com/stretchr/testify/require"

)


func TestFlaky(t *testing.T) {

    // Mock an API

    http.HandleFunc("/foo/bar", func(w http.ResponseWriter, r *http.Request) {

        _, err := w.Write([]byte("foobar"))

        require.NoError(t, err)

    })

    go func() {

        require.NoError(t, http.ListenAndServe("localhost:7777", nil))

    }()


    // Wait (up to 1 second) for the mocked API to be available

    conn, err := net.DialTimeout("tcp", "localhost:7777", time.Second)

    require.NoError(t, err)

    require.NoError(t, conn.Close())

}

但是,从错误之后的行中,我收到以下错误(仅在CI环境中):require.NoError()DialTimeout


     --- FAIL: TestFlaky (0.00s)

         main_test.go:24: 

                Error Trace:    main_test.go:24

                Error:          Received unexpected error:

                                dial tcp [::1]:7777: connect: connection refused

                Test:           TestFlaky

由于测试立即失败,我猜这不是调整超时的问题。我应该如何使这个测试不片状?我正在考虑将最后三行替换为类似于以下内容的行:require.Eventually


    var conn net.Conn

    require.Eventually(t, func() bool {

        var err error

        conn, err = net.DialTimeout("tcp", "localhost:7777", time.Second)

        if err != nil {

            t.Logf("DialTimeout error: %v. Retrying...", err)

            return false

        }

        return true

    }, time.Second, 100*time.Millisecond)

    require.NoError(t, conn.Close())

这是否足以消除测试剥落?


弑天下
浏览 75回答 1
1回答

蛊毒传说

goroutine内部的代码不能保证在拨号之前执行(如果你在大流子之后睡觉,它应该可以工作,但这是一个丑陋的解决方案)。另请注意,当连接稳定时,“超时拨号”正在等待 tcp 数据包,但拒绝的连接实际上是 RST 数据包。提示:看看 httptest 包是如何工作的。编辑:这是 httptest 的工作原理:https://cs.opensource.google/go/go/+/refs/tags/go1.16.6:src/net/http/httptest/server.go;l=304func (s *Server) goServe() {    s.wg.Add(1)    go func() {        defer s.wg.Done()        s.Config.Serve(s.Listener)    }()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go