为了账号安全,请及时绑定邮箱和手机立即绑定

在测试期间同步测试服务器

在测试期间同步测试服务器

Go
慕无忌1623718 2023-06-26 18:06:05
摘要:我在测试过程中遇到了竞争状况,我的服务器在向其发出客户端请求之前尚未可靠地准备好服务请求。如何仅在侦听器准备好之前进行阻止,并且仍然维护可组合的公共 API,而不要求用户 BYO net.Listener?client.Do(req)我们看到以下错误,因为在我们调用测试函数之前,在后台启动(阻塞)服务器的 goroutine 没有监听TestRun。--- FAIL: TestRun/Server_accepts_HTTP_requests (0.00s)         /home/matt/repos/admission-control/server_test.go:64: failed to make a request: Get https://127.0.0.1:37877: dial tcp 127.0.0.1:37877: connect: connection refused我没有httptest.Server直接使用,因为我正在尝试测试我自己的服务器组件的阻止和取消特性。我创建一个,在使用 启动它后将httptest.NewUnstartedServer其克隆*tls.Config到一个新的中,然后在调用 之前将其关闭。这还有一个好处是为我提供了配置了匹配的 RootCA。http.ServerStartTLS()*AdmissionServer.Run()*http.Client测试 TLS 在这里很重要,因为它公开的守护进程存在于仅 TLS 的环境中。func newTestServer(ctx context.Context, t *testing.T) *httptest.Server {    testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        fmt.Fprintln(w, "OK")    })    testSrv := httptest.NewUnstartedServer(testHandler)    admissionServer, err := NewServer(nil, &noopLogger{})    if err != nil {        t.Fatalf("admission server creation failed: %s", err)        return nil    }    // We start the test server, copy its config out, and close it down so we can    // start our own server. This is because httptest.Server only generates a    // self-signed TLS config after starting it.    testSrv.StartTLS()    admissionServer.srv = &http.Server{        Addr:      testSrv.Listener.Addr().String(),        Handler:   testHandler,        TLSConfig: testSrv.TLS.Clone(),    }    testSrv.Close()    // We need a better synchronization primitive here that doesn't block    // but allows the underlying listener to be ready before     // serving client requests.    go func() {        if err := admissionServer.Run(ctx); err != nil {            t.Fatalf("server returned unexpectedly: %s", err)        }    }()    return testSrv}
查看完整描述

1 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

作为初始化过程的一部分,您可以在启动测试套件之前尝试连接到服务器。


例如,我在测试中通常有这样的函数:


// waitForServer attempts to establish a TCP connection to localhost:<port>

// in a given amount of time. It returns upon a successful connection; 

// ptherwise exits with an error.

func waitForServer(port string) {

    backoff := 50 * time.Millisecond


    for i := 0; i < 10; i++ {

        conn, err := net.DialTimeout("tcp", ":"+port, 1*time.Second)

        if err != nil {

            time.Sleep(backoff)

            continue

        }

        err = conn.Close()

        if err != nil {

            log.Fatal(err)

        }

        return

    }

    log.Fatalf("Server on port %s not up after 10 attempts", port)

}

然后在我的TestMain()我做:


func TestMain(m *testing.M) {

    go startServer()

    waitForServer(serverPort)


    // run the suite

    os.Exit(m.Run())

}


查看完整回答
反对 回复 2023-06-26
  • 1 回答
  • 0 关注
  • 108 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信