猿问

使用 httptest 和 curl 的不同内容类型

我正在尝试这个 Go 代码


package main


import (

    "github.com/gorilla/mux"

    "io"

    "log"

    "net/http"

)


func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {

    w.WriteHeader(http.StatusOK)

    w.Header().Set("Content-Type", "application/json")


    io.WriteString(w, `{"alive": true}`)

}


func main() {


    router := mux.NewRouter()

    router.HandleFunc("/health", HealthCheckHandler).Methods("GET")


    log.Printf("running server ...")

    log.Fatal(http.ListenAndServe(":8000", router))

}

通过这个测试


package main


import (

    "net/http"

    "net/http/httptest"

    "testing"

)


func TestHealthCheckHandler(t *testing.T) {

    req, err := http.NewRequest("GET", "/health", nil)

    if err != nil {

        t.Fatal(err)

    }

    rr := httptest.NewRecorder()

    handler := http.HandlerFunc(HealthCheckHandler)


    handler.ServeHTTP(rr, req)


    if status := rr.Code; status != http.StatusOK {

        t.Errorf("handler returned wrong status code: got %v want %v",

            status, http.StatusOK)

    }


    t.Logf("%v", rr.Header())


    if ctype := rr.Header().Get("Content-Type"); ctype != "application/json" {

        t.Errorf("content type header does not match: got %v want %v",

            ctype, "application/json")

    }

}

当我运行测试时,一切正常


go test -v

=== RUN   TestHealthCheckHandler

--- PASS: TestHealthCheckHandler (0.00s)

    handlers_test.go:24: map[Content-Type:[application/json]]

PASS

ok          0.012s

是,但是当我运行该服务并用 curl 调用它时Content-Type,是application/jsonContent-Typetext/plain


curl -v localhost:8000/health

*   Trying ::1...

* Connected to localhost (::1) port 8000 (#0)

> GET /health HTTP/1.1

> Host: localhost:8000

> User-Agent: curl/7.43.0

> Accept: */*

>

< HTTP/1.1 200 OK

< Date: Thu, 14 Feb 2019 01:37:15 GMT

< Content-Length: 15

< Content-Type: text/plain; charset=utf-8

<

* Connection #0 to host localhost left intact

为什么行为不同于测试和执行?


慕姐8265434
浏览 114回答 2
2回答

MMMHUHU

问题是您在标题之前发送了身体。这在任何语言中都行不通——这是 HTTP 的事实,而不是 Go 的事实。它没有被您的测试捕获的原因是您的测试实际上是在滥用ResponseRecorder;您在地图中设置字段,然后直接从该地图读取字段。测试应该只检查ResponseRecorder.Result,它旨在为您提供客户端实际收到的结果,包括在发送正文时锁定标头:if ctype := rr.Response().Header.Get("Content-Type"); ctype != "application/json" {&nbsp; &nbsp; t.Errorf("content type header does not match: got %v want %v",&nbsp; &nbsp; &nbsp; &nbsp; ctype, "application/json")}

婷婷同学_

只需将您的功能更改为:func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; // this will cause a duplicate status header to be written&nbsp; &nbsp; // w.WriteHeader(http.StatusOK)&nbsp; &nbsp; w.Header().Set("Content-Type", "application/json")&nbsp; &nbsp; io.WriteString(w, `{"alive": true}`)}
随时随地看视频慕课网APP

相关分类

Go
我要回答