3 回答

TA貢獻1864條經驗 獲得超2個贊
gorilla/mux提供SetURLVars用于測試目的的函數,您可以使用它來注入您的 mock vars。
func TestGetRequest(t *testing.T) {
t.Parallel()
r, _ := http.NewRequest("GET", "/test/abcd", nil)
w := httptest.NewRecorder()
//Hack to try to fake gorilla/mux vars
vars := map[string]string{
"mystring": "abcd",
}
// CHANGE THIS LINE!!!
r = mux.SetURLVars(r, vars)
GetRequest(w, r)
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, []byte("abcd"), w.Body.Bytes())
}

TA貢獻1795條經驗 獲得超7個贊
問題是,即使您使用0as 值來設置上下文值,mux.Vars()讀取的值也不是相同的。mux.Vars()正在使用varsKey(正如您已經看到的)類型contextKey而不是int.
當然,contextKey定義為:
type contextKey int
這意味著它具有 int 作為底層對象,但在比較 go 中的值時,類型會起作用,因此int(0) != contextKey(0).
我不明白你怎么能欺騙大猩猩多路復用器或上下文來返回你的值。
話雖如此,我想到了幾種測試方法(請注意,下面的代碼未經測試,我直接在此處輸入,因此可能存在一些愚蠢的錯誤):
正如有人建議的那樣,運行一個服務器并向它發送 HTTP 請求。
無需運行服務器,只需在測試中使用 gorilla mux Router。在這種情況下,您將有一個傳遞給 的路由器ListenAndServe,但您也可以在測試中使用相同的路由器實例并調用ServeHTTP它。路由器將負責設置上下文值,它們將在您的處理程序中可用。
func Router() *mux.Router {
r := mux.Router()
r.HandleFunc("/employees/{1}", GetRequest)
(...)
return r
}
在 main 函數的某個地方,你會做這樣的事情:
http.Handle("/", Router())
在您的測試中,您可以執行以下操作:
func TestGetRequest(t *testing.T) {
r := http.NewRequest("GET", "employees/1", nil)
w := httptest.NewRecorder()
Router().ServeHTTP(w, r)
// assertions
}
包裝您的處理程序,以便它們接受 URL 參數作為第三個參數,并且包裝器應調用mux.Vars()URL 參數并將其傳遞給處理程序。
使用此解決方案,您的處理程序將具有簽名:
type VarsHandler func (w http.ResponseWriter, r *http.Request, vars map[string]string)
并且您必須調整對它的調用以符合http.Handler接口:
func (vh VarsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
vh(w, r, vars)
}
要注冊處理程序,您將使用:
func GetRequest(w http.ResponseWriter, r *http.Request, vars map[string]string) {
// process request using vars
}
mainRouter := mux.NewRouter().StrictSlash(true)
mainRouter.HandleFunc("/test/{mystring}", VarsHandler(GetRequest)).Name("/test/{mystring}").Methods("GET")
您使用哪一種取決于個人喜好。就我個人而言,我可能會選擇選項 2 或 3,稍微偏向于選項 3。

TA貢獻1802條經驗 獲得超5個贊
在 golang 中,我的測試方法略有不同。
我稍微重寫了你的 lib 代碼:
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
)
func main() {
startServer()
}
func startServer() {
mainRouter := mux.NewRouter().StrictSlash(true)
mainRouter.HandleFunc("/test/{mystring}", GetRequest).Name("/test/{mystring}").Methods("GET")
http.Handle("/", mainRouter)
err := http.ListenAndServe(":8080", mainRouter)
if err != nil {
fmt.Println("Something is wrong : " + err.Error())
}
}
func GetRequest(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
myString := vars["mystring"]
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte(myString))
}
這是對它的測試:
package main
import (
"io/ioutil"
"net/http"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestGetRequest(t *testing.T) {
go startServer()
client := &http.Client{
Timeout: 1 * time.Second,
}
r, _ := http.NewRequest("GET", "http://localhost:8080/test/abcd", nil)
resp, err := client.Do(r)
if err != nil {
panic(err)
}
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
assert.Equal(t, []byte("abcd"), body)
}
我認為這是一個更好的方法——你真的在測試你寫的東西,因為它很容易在 go 中啟動/停止偵聽器!
- 3 回答
- 0 關注
- 363 瀏覽
添加回答
舉報