猿问

去关闭僵局

尝试在 Go 测试中模拟 http 响应。如果我运行它,下面的代码片段永远不会终止


去测试example.com/auth/...


package auth_test

import (

    "testing"

    "net/http/httptest"

    "net/http"

)


func TestAuthorization(t *testing.T) {

    t.Log("Should return 401 when Gateway returns 401")

    {

        url := oneOffUrlWithResponseCode(http.StatusUnauthorized)

        request, _ := http.NewRequest("GET", url, nil)

        response, _ := http.DefaultClient.Do(request)


        if response.StatusCode != http.StatusUnauthorized {

            t.Fatalf("Response should be 401 (Unauthorized)")

        }

    }

}


func oneOffUrlWithResponseCode(responseCode int) string {

    var server *httptest.Server

    server = httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {

        defer server.Close()

        response.WriteHeader(responseCode)

    }))

    return server.URL

}

但是,如果我注释掉这一行


延迟 server.Close()


一切正常。


理想情况下,我不想在 oneOffUrlWithResponseCode 函数之外“泄漏” *httptest.Server 并且显然在第一次请求后关闭它。


为什么它永远不会终止?我究竟做错了什么?正确的做法是什么?


心有法竹
浏览 162回答 1
1回答

慕勒3428872

程序不会因为死锁而终止(它与闭包无关)。您不能Close在处理程序内部调用,因为在内部Close等待所有处理程序完成。修复它的最简单方法是在 oneOffUrlWithResponseCode 之外“泄漏”httptest.Server:func TestAuthorization(t *testing.T) {    ...    server := oneOffUrlWithResponseCode(http.StatusUnauthorized)    defer server.Close()    request, _ := http.NewRequest("GET", server.URL, nil)    ...}func oneOffUrlWithResponseCode(responseCode int) *httptest.Server {    return httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {        response.WriteHeader(responseCode)    }))}
随时随地看视频慕课网APP
我要回答