英文:
Simple test for alexedwards/scs using only the public api
问题
这个问题是对这个问题的后续问题。我想要一个简单的测试来验证我想要使用的函数,测试的网址是https://pkg.go.dev/github.com/alexedwards/scs/v2@v2.5.1。基本上,我只想把一些数据放入会话中,取出来,并验证它是否相同。类似这样的代码:
func TestScs_SetGetIsSame1(t *testing.T) {
sessionManager := scs.New()
req := httptest.NewRequest("GET", "/", nil)
key := "boolean"
expected := false
sessionManager.Put(req.Context(), key, expected)
actual := sessionManager.GetBool(req.Context(), key)
assert.Equal(t, expected, actual)
}
这会导致 panic: scs: no session data in context。
我尝试复制httptest 包中的示例,但是 httptest.Server 没有实现 http.Handler(缺少 ServeHTTP 方法)。
func TestScs_SetGetIsSame2(t *testing.T) {
sessionManager := scs.New()
ts := httptest.NewServer((http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
expected := true
sessionManager.Put(r.Context(), "key", expected)
actual := sessionManager.GetBool(r.Context(), "key")
assert.Equal(t, expected, actual)
})))
defer ts.Close()
res, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
greeting, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", greeting)
sessionManager.LoadAndSave(ts)
}
我还查看了 alexedwards/scs 仓库中的测试,但它们使用了一个私有函数 addSessionDataToContext。
在 Go 中,测试会话的最佳、最简单的方法是什么?
英文:
This question is a follow-up question to this one. I would like a simple test for https://pkg.go.dev/github.com/alexedwards/scs/v2@v2.5.1 to verify the functions I would like to use. Basically, I just want to put some data into the session, pull it out, and verify it is the same. Something like:
func TestScs_SetGetIsSame1(t *testing.T) {
sessionManager := scs.New()
req := httptest.NewRequest("GET", "/", nil)
key := "boolean"
expected := false
sessionManager.Put(req.Context(), key, expected)
actual := sessionManager.GetBool(req.Context(), key)
assert.Equal(t, expected, actual)
}
This gives panic: scs: no session data in context.
I tried copying the example from the httptest package, but httptest.Server does not implement http.Handler (missing method ServeHTTP).
func TestScs_SetGetIsSame2(t *testing.T) {
sessionManager := scs.New()
ts := httptest.NewServer((http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
expected := true
sessionManager.Put(r.Context(), "key", expected)
actual := sessionManager.GetBool(r.Context(), "key")
assert.Equal(t, expected, actual)
})))
defer ts.Close()
res, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
greeting, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", greeting)
sessionManager.LoadAndSave(ts)
}
I also looked at the tests in the alexedwards/scs repository, but they use a private function addSessionDataToContext.
What is the best, most simple way to test sessions in go?
答案1
得分: 1
我在你的代码中看到了以下内容:
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// ...
}))
sessionManager.LoadAndSave(ts) // 这一行是错误的
你试图将测试服务器 (ts
) 传递给 sessionManager.LoadAndSave
。这样是行不通的,因为 sessionManager.LoadAndSave
需要一个 http.Handler
,而 ts
的类型是 *httptest.Server
,而不是 http.Handler
。
相反,在创建测试服务器之前,你应该将实际的处理程序传递给 sessionManager.LoadAndSave
。
为此,你需要使用 sessionManager.LoadAndSave
将实际的处理程序函数包装起来(它返回一个 http.Handler
),然后将其传递给 httptest.NewServer
。
handler := sessionManager.LoadAndSave(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// ... 在这里编写逻辑 ...
}))
ts := httptest.NewServer(handler)
这样就通过使用 sessionManager.LoadAndSave
中间件将实际的处理程序函数包装成了一个新的处理程序。然后将这个包装后的处理程序传递给 httptest.NewServer
。
将所有这些组合在一起:
package main
import (
"fmt"
"github.com/alexedwards/scs/v2"
"github.com/stretchr/testify/assert"
"io"
"log"
"net/http"
"net/http/httptest"
"testing"
)
func TestScs_SetGetIsSame2(t *testing.T) {
sessionManager := scs.New()
// 创建一个处理程序并使用 sessionManager.LoadAndSave 进行包装
handler := sessionManager.LoadAndSave(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
expected := true
sessionManager.Put(r.Context(), "key", expected)
actual := sessionManager.GetBool(r.Context(), "key")
assert.Equal(t, expected, actual)
}))
// 使用处理程序创建一个测试服务器
ts := httptest.NewServer(handler)
defer ts.Close()
// 向服务器发起请求
res, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
// 读取响应体
greeting, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
// 打印响应体
fmt.Printf("%s", greeting)
}
希望对你有所帮助!
英文:
I see in your code
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// ...
}))
sessionManager.LoadAndSave(ts) // this line is incorrect
You are trying to pass the test server (ts
) to sessionManager.LoadAndSave
. This will not work because sessionManager.LoadAndSave
expects an http.Handler
, and ts
is of type *httptest.Server
, not http.Handler
.
Instead, you should pass the actual handler to sessionManager.LoadAndSave
before creating the test server.
For that, you would wrap the actual handler function with sessionManager.LoadAndSave
(which does return a http.Handler
) before passing it to httptest.NewServer
.
handler := sessionManager.LoadAndSave(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// ... logic here ...
}))
ts := httptest.NewServer(handler)
That creates a new handler by wrapping your actual handler function with the sessionManager.LoadAndSave
middleware. This wrapped handler is then passed to httptest.NewServer
.
If you bring it all together:
package main
import (
"fmt"
"github.com/alexedwards/scs/v2"
"github.com/stretchr/testify/assert"
"io"
"log"
"net/http"
"net/http/httptest"
"testing"
)
func TestScs_SetGetIsSame2(t *testing.T) {
sessionManager := scs.New()
// Create a handler and wrap it using sessionManager.LoadAndSave
handler := sessionManager.LoadAndSave(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
expected := true
sessionManager.Put(r.Context(), "key", expected)
actual := sessionManager.GetBool(r.Context(), "key")
assert.Equal(t, expected, actual)
}))
// Create a test server with the handler
ts := httptest.NewServer(handler)
defer ts.Close()
// Make a request to the server
res, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
// Read the response body
greeting, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
// Print the response body
fmt.Printf("%s", greeting)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论