【问题标题】:Go closure deadlockGo 关闭死锁
【发布时间】:2015-10-12 01:10:42
【问题描述】:

尝试在 Go 测试中模拟 http 响应。如果我用

运行下面的代码 sn-p 永远不会终止

去测试 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 并且在第一次请求后显然将其关闭。

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

【问题讨论】:

  • 只是好奇,为什么要隐藏服务器。返回服务器似乎很合理,因为它预计将用于测试,例如。服务器被创建并且服务器被测试关闭(而不是在它的回调中)。

标签: unit-testing go closures


【解决方案1】:

程序不会因为死锁而终止(它与闭包无关)。您不能在处理程序内部调用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)
    }))
}

【讨论】:

  • 我想指出的另一种选择是可以完全避免使用服务器。处理程序可以在httptest.ResponseRecorderhttp.Request 上调用。使用ResponseRecorder,您可以检查.Code 并看到它应该已更新为http.StatusUnauthorized,因为测试下的代码没有做太多。唯一的区别是这是一个单元测试还是一个集成测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 2011-05-29
  • 2017-06-24
  • 2018-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多