尝试在Go测试中模拟http响应。如果我使用
运行它,下面的代码片段永远不会终止go test 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()
理想情况下,我不想"泄漏" * http:。在oneOffUrlWithResponseCode函数之外的服务器,并在第一次请求后明显关闭它。
为什么它永远不会终止?我究竟做错了什么?什么是正确的做法?
答案 0 :(得分:4)
程序不会因为死锁而终止(并且它与闭包无关)。您无法在处理程序内调用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)
}))
}