這裏就是我想要做的事:單元測試/ MUX URL參數
main.go
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
)
func main() {
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))
}
這將創建一個基本的HTTP服務器偵聽端口8080
那回應路徑中給出的URL參數。因此,對於http://localhost:8080/test/abcd
,它將在響應正文中回寫包含abcd
的響應。
爲GetRequest()
功能的單元測試是在main_test.go:
package main
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gorilla/context"
"github.com/stretchr/testify/assert"
)
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",
}
context.Set(r, 0, vars)
GetRequest(w, r)
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, []byte("abcd"), w.Body.Bytes())
}
測試結果是:
--- FAIL: TestGetRequest (0.00s)
assertions.go:203:
Error Trace: main_test.go:27
Error: Not equal: []byte{0x61, 0x62, 0x63, 0x64} (expected)
!= []byte(nil) (actual)
Diff:
--- Expected
+++ Actual
@@ -1,4 +1,2 @@
-([]uint8) (len=4 cap=8) {
- 00000000 61 62 63 64 |abcd|
-}
+([]uint8) <nil>
FAIL
FAIL command-line-arguments 0.045s
的問題是我怎麼假的mux.Vars(r)
爲單位測試? 我發現一些討論here但建議的解決方案不再有效。所提出的解決方案是:
func buildRequest(method string, url string, doctype uint32, docid uint32) *http.Request {
req, _ := http.NewRequest(method, url, nil)
req.ParseForm()
var vars = map[string]string{
"doctype": strconv.FormatUint(uint64(doctype), 10),
"docid": strconv.FormatUint(uint64(docid), 10),
}
context.DefaultContext.Set(req, mux.ContextKey(0), vars) // mux.ContextKey exported
return req
}
此解決方案不起作用,因爲context.DefaultContext
和mux.ContextKey
不復存在。
另一個建議的解決方案是更改您的代碼,以便請求函數也接受map[string]string
作爲第三個參數。其他解決方案包括實際啓動服務器並構建請求並將其直接發送到服務器。在我看來,這將打破單元測試的目的,將它們轉化爲功能測試。
考慮到鏈接的線程是2013年的事實。有沒有其他的選擇?
EDIT
因此,我已閱讀gorilla/mux
源代碼,並根據mux.go
功能mux.Vars()
這樣定義here:
// Vars returns the route variables for the current request, if any.
func Vars(r *http.Request) map[string]string {
if rv := context.Get(r, varsKey); rv != nil {
return rv.(map[string]string)
}
return nil
}
的varsKey
的值被定義爲iota
here 。所以本質上,關鍵值是0
。我寫了一個小的測試應用程序進行檢查: main.go
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/gorilla/context"
)
func main() {
r, _ := http.NewRequest("GET", "/test/abcd", nil)
vars := map[string]string{
"mystring": "abcd",
}
context.Set(r, 0, vars)
what := Vars(r)
for key, value := range what {
fmt.Println("Key:", key, "Value:", value)
}
what2 := mux.Vars(r)
fmt.Println(what2)
for key, value := range what2 {
fmt.Println("Key:", key, "Value:", value)
}
}
func Vars(r *http.Request) map[string]string {
if rv := context.Get(r, 0); rv != nil {
return rv.(map[string]string)
}
return nil
}
,當運行,輸出:
Key: mystring Value: abcd
map[]
這使我想知道爲什麼測試不工作,爲什麼直接撥打mux.Vars
不起作用。
謝謝。我想我會使用選項3.但是'大猩猩/多路複用器'應該解決這個問題,使單元測試成爲可能。 –
我通過檢查gorilla/mux在自己的包中測試的方式解決了這個問題,並且在處理程序中將自己的斷言放在了'vars'的值處:https://github.com/gorilla/mux /blob/master/context_native_test.go#L22 – xentek