如何测试实现了Gorilla上下文的函数?

huangapple go评论112阅读模式
英文:

How to test functions that implement gorilla context

问题

我写了一个将数据保存到Redis数据库服务器的函数。挑战在于我想测试这些函数,但不知道如何测试。

我只是以某种方式开始了以下代码:

  1. package sessrage
  2. /*
  3. * 将数据保存到Redis数据库。通常情况下,数据只在请求期间有效。在Redis中使用哈希数据类型。
  4. */
  5. import (
  6. "../context"
  7. "github.com/garyburd/redigo/redis"
  8. "net/http"
  9. )
  10. const (
  11. protocol string = "tcp"
  12. port string = ":6379"
  13. )
  14. func connectAndCloseRedis(connectCall func(con redis.Conn)) {
  15. c, err := redis.Dial("tcp", ":6379")
  16. defer c.Close()
  17. if err != nil {
  18. panic(err.Error())
  19. }
  20. connectCall(c)
  21. }
  22. func PostSessionData(r *http.Request, key, value string) {
  23. go connectAndCloseRedis(func(con redis.Conn) {
  24. sessionId := context.Get(r, context.JwtId).(string)
  25. con.Do("HMSET", sessionId, key, value)
  26. })
  27. }
  28. func GetSessionData(r *http.Request, key string) interface{} {
  29. var result interface{}
  30. sessionId := context.Get(r, context.JwtId).(string)
  31. reply, _ := redis.Values(c.Do("HMGET", sessionId, key))
  32. redis.Scan(reply, &result)
  33. return result
  34. }

测试文件如下:

  1. package sessrage
  2. import (
  3. //"fmt"
  4. "../context"
  5. . "github.com/smartystreets/goconvey/convey"
  6. "github.com/stretchr/testify/assert"
  7. "net/http"
  8. "net/http/httptest"
  9. "testing"
  10. "time"
  11. )
  12. var server *httptest.Server
  13. var glrw http.ResponseWriter
  14. var glr *http.Request
  15. func init() {
  16. server = httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  17. glrw = rw
  18. glr = r
  19. context.Set(glr, context.JwtId, "TestId")
  20. }))
  21. }
  22. func TestPostAndGetSession(t *testing.T) {
  23. Convey("POST and GET data on redis.", t, func() {
  24. PostSessionData(glr, "key1", "value1")
  25. time.Sleep(time.Second * 10)
  26. v := GetSessionData(glr, "key1")
  27. assert.Equal(t, "value1", v)
  28. })
  29. }

当我尝试运行测试时,我得到以下错误:

  1. 无法加载包:......./sessrage.go:10:2: 非本地包中的本地导入 "../context"

context包的代码如下:

  1. package context
  2. import (
  3. "github.com/gorilla/context"
  4. "net/http"
  5. )
  6. type contextKey int
  7. const (
  8. LanguageId contextKey = iota
  9. JwtId
  10. )
  11. func Get(r *http.Request, key interface{}) interface{} {
  12. return context.Get(r, key)
  13. }
  14. func Set(r *http.Request, key, val interface{}) {
  15. context.Set(r, key, val)
  16. }

我做错了什么?

这是我第一次在与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

  1. package sessrage
  2. /*
  3. * Save data into redis database. In the common case,
  4. * the data will be only valid during a request. Use
  5. * hash datatype in redis.
  6. */
  7. import (
  8. "../context"
  9. "github.com/garyburd/redigo/redis"
  10. "net/http"
  11. )
  12. const (
  13. protocol string = "tcp"
  14. port string = ":6379"
  15. )
  16. func connectAndCloseRedis(connectCall func(con redis.Conn)) {
  17. c, err := redis.Dial("tcp", ":6379")
  18. defer c.Close()
  19. if err != nil {
  20. panic(err.Error())
  21. }
  22. connectCall(c)
  23. }
  24. func PostSessionData(r *http.Request, key, value string) {
  25. go connectAndCloseRedis(func(con redis.Conn) {
  26. sessionId := context.Get(r, context.JwtId).(string)
  27. con.Do("HMSET", sessionId, key, value)
  28. })
  29. }
  30. func GetSessionData(r *http.Request, key string) interface{} {
  31. var result interface{}
  32. sessionId := context.Get(r, context.JwtId).(string)
  33. reply, _ := redis.Values(c.Do("HMGET", sessionId, key))
  34. redis.Scan(reply, &result)
  35. return result
  36. }

and the test file

  1. package sessrage
  2. import (
  3. //"fmt"
  4. "../context"
  5. . "github.com/smartystreets/goconvey/convey"
  6. "github.com/stretchr/testify/assert"
  7. "net/http"
  8. "net/http/httptest"
  9. "testing"
  10. "time"
  11. )
  12. var server *httptest.Server
  13. var glrw http.ResponseWriter
  14. var glr *http.Request
  15. func init() {
  16. server = httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  17. glrw = rw
  18. glr = r
  19. context.Set(glr, context.JwtId, "TestId")
  20. }))
  21. }
  22. func TestPostAndGetSession(t *testing.T) {
  23. Convey("POST and GET data on redis.", t, func() {
  24. PostSessionData(glr, "key1", "value1")
  25. time.Sleep(time.Second * 10)
  26. v := GetSessionData(glr, "key1")
  27. assert.Equal(t, "value1", v)
  28. })
  29. }

when I try to run the test I've got

  1. an't load package: ......./sessrage.go:10:2: local import "../context" in non-local package

and the context package looks like

  1. package context
  2. import (
  3. "github.com/gorilla/context"
  4. "net/http"
  5. )
  6. type contextKey int
  7. const (
  8. LanguageId contextKey = iota
  9. JwtId
  10. )
  11. func Get(r *http.Request, key interface{}) interface{} {
  12. return context.Get(r, key)
  13. }
  14. func Set(r *http.Request, key, val interface{}) {
  15. context.Set(r, key, val)
  16. }

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上下文。改为使用以下代码:

    1. func PostSessionData(r *http.Request, key, value string) {
    2. c := pool.Get()
    3. defer c.Close()
    4. sessionId := context.Get(r, context.JwtId).(string)
    5. if err := c.Do("HMSET", sessionId, key, value); err != nil {
    6. // 处理错误
    7. }
    8. }
英文:

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:

    1. func PostSessionData(r *http.Request, key, value string) {
    2. c := pool.Get()
    3. defer c.Close()
    4. sessionId := context.Get(r, context.JwtId).(string)
    5. if err := c.Do("HMSET", sessionId, key, value); err != nil {
    6. // handle error
    7. }
    8. }

huangapple
  • 本文由 发表于 2014年10月17日 03:18:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/26412201.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定