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 关注
- 270 浏览
添加回答
举报