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

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

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
          }
      }
    

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:

确定