gpt4 book ai didi

unit-testing - 对使用 gorilla/mux URL 参数的函数进行单元测试

转载 作者:IT老高 更新时间:2023-10-28 13:02:42 53 4
gpt4 key购买 nike

TLDR:gorilla/mux 过去不提供设置 URL Vars 的可能性。现在确实如此,这就是为什么在很长一段时间内,第二高的答案是正确答案。

要遵循的原始问题:


这就是我想要做的:

ma​​in.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() 函数的单元测试在 ma​​in_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.DefaultContextmux.ContextKey 不再存在。

另一个建议的解决方案是更改您的代码,以便请求函数也接受 map[string]string 作为第三个参数。其他解决方案包括实际启动服务器并构建请求并将其直接发送到服务器。在我看来,这会破坏单元测试的目的,将它们本质上变成功能测试。

考虑到链接线程来自 2013 年的事实。还有其他选择吗?

编辑

所以我已经阅读了 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。我编写了一个小型测试应用程序来检查这一点:ma​​in.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 不起作用。

最佳答案

gorilla/mux 提供 SetURLVars用于测试目的的函数,您可以使用它来注入(inject)您的模拟 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())
}

关于unit-testing - 对使用 gorilla/mux URL 参数的函数进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34435185/

53 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com