英文:
How to test functions that implement gorilla context
问题
我写了一个将数据保存到Redis数据库服务器的函数。挑战在于我想测试这些函数,但不知道如何测试。
我只是以某种方式开始了以下代码:
package sessrage
/*
* 将数据保存到Redis数据库。通常情况下,数据只在请求期间有效。在Redis中使用哈希数据类型。
*/
import (
"../context"
"github.com/garyburd/redigo/redis"
"net/http"
)
const (
protocol string = "tcp"
port string = ":6379"
)
func connectAndCloseRedis(connectCall func(con redis.Conn)) {
c, err := redis.Dial("tcp", ":6379")
defer c.Close()
if err != nil {
panic(err.Error())
}
connectCall(c)
}
func PostSessionData(r *http.Request, key, value string) {
go connectAndCloseRedis(func(con redis.Conn) {
sessionId := context.Get(r, context.JwtId).(string)
con.Do("HMSET", sessionId, key, value)
})
}
func GetSessionData(r *http.Request, key string) interface{} {
var result interface{}
sessionId := context.Get(r, context.JwtId).(string)
reply, _ := redis.Values(c.Do("HMGET", sessionId, key))
redis.Scan(reply, &result)
return result
}
测试文件如下:
package sessrage
import (
//"fmt"
"../context"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
"time"
)
var server *httptest.Server
var glrw http.ResponseWriter
var glr *http.Request
func init() {
server = httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
glrw = rw
glr = r
context.Set(glr, context.JwtId, "TestId")
}))
}
func TestPostAndGetSession(t *testing.T) {
Convey("POST and GET data on redis.", t, func() {
PostSessionData(glr, "key1", "value1")
time.Sleep(time.Second * 10)
v := GetSessionData(glr, "key1")
assert.Equal(t, "value1", v)
})
}
当我尝试运行测试时,我得到以下错误:
无法加载包:......./sessrage.go:10:2: 非本地包中的本地导入 "../context"
而context
包的代码如下:
package context
import (
"github.com/gorilla/context"
"net/http"
)
type contextKey int
const (
LanguageId contextKey = iota
JwtId
)
func Get(r *http.Request, key interface{}) interface{} {
return context.Get(r, key)
}
func Set(r *http.Request, key, val interface{}) {
context.Set(r, key, val)
}
我做错了什么?
这是我第一次在与HTTP一起测试代码。测试似乎非常困难。
英文:
I wrote a functions that save data into redis database server. The challenge is that I want to test these functions and do not know how to test it.
I just start somehow with
Functions
package sessrage
/*
* Save data into redis database. In the common case,
* the data will be only valid during a request. Use
* hash datatype in redis.
*/
import (
"../context"
"github.com/garyburd/redigo/redis"
"net/http"
)
const (
protocol string = "tcp"
port string = ":6379"
)
func connectAndCloseRedis(connectCall func(con redis.Conn)) {
c, err := redis.Dial("tcp", ":6379")
defer c.Close()
if err != nil {
panic(err.Error())
}
connectCall(c)
}
func PostSessionData(r *http.Request, key, value string) {
go connectAndCloseRedis(func(con redis.Conn) {
sessionId := context.Get(r, context.JwtId).(string)
con.Do("HMSET", sessionId, key, value)
})
}
func GetSessionData(r *http.Request, key string) interface{} {
var result interface{}
sessionId := context.Get(r, context.JwtId).(string)
reply, _ := redis.Values(c.Do("HMGET", sessionId, key))
redis.Scan(reply, &result)
return result
}
and the test file
package sessrage
import (
//"fmt"
"../context"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
"time"
)
var server *httptest.Server
var glrw http.ResponseWriter
var glr *http.Request
func init() {
server = httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
glrw = rw
glr = r
context.Set(glr, context.JwtId, "TestId")
}))
}
func TestPostAndGetSession(t *testing.T) {
Convey("POST and GET data on redis.", t, func() {
PostSessionData(glr, "key1", "value1")
time.Sleep(time.Second * 10)
v := GetSessionData(glr, "key1")
assert.Equal(t, "value1", v)
})
}
when I try to run the test I've got
an't load package: ......./sessrage.go:10:2: local import "../context" in non-local package
and the context package looks like
package context
import (
"github.com/gorilla/context"
"net/http"
)
type contextKey int
const (
LanguageId contextKey = iota
JwtId
)
func Get(r *http.Request, key interface{}) interface{} {
return context.Get(r, key)
}
func Set(r *http.Request, key, val interface{}) {
context.Set(r, key, val)
}
What do I wrong?
That is the first time, I am testing code in conjunction with http. It seems to be very hard to test.
答案1
得分: 1
有几个问题:
-
不要使用相对导入路径。
-
在每个操作中使用一个池,而不是每次都拨号到redis。
-
在PostSessionData匿名函数中的sessionId := context.Get(r, context.JwtId).(string)调用可能会失败,如果mux或调用链中的其他高级组件在goroutine运行之前清除了Gorilla上下文。改为使用以下代码:
func PostSessionData(r *http.Request, key, value string) { c := pool.Get() defer c.Close() sessionId := context.Get(r, context.JwtId).(string) if err := c.Do("HMSET", sessionId, key, value); err != nil { // 处理错误 } }
英文:
There are a few issues:
-
Don't use relative import paths.
-
Use a pool instead of dialing redis on every action.
-
The call to sessionId := context.Get(r, context.JwtId).(string) in the PostSessionData anonymous function can fail if the mux or something higher in the call chain clears the Gorilla context before the goroutine runs. Do this instead:
func PostSessionData(r *http.Request, key, value string) { c := pool.Get() defer c.Close() sessionId := context.Get(r, context.JwtId).(string) if err := c.Do("HMSET", sessionId, key, value); err != nil { // handle error } }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论