如何动态更改方法接收器

我最近了解到你可以在go中做到这一点:


type Env struct{}


func (e *Env) httpHandler(w http.ResponseWriter, r *http.Request) {

   //...

}


func main() {

    // ...

    e := &Env{}

    router := mux.NewRouter()

    router.HandleFunc("/foo", e.httpHandler)

}

这对于依赖注入非常有用,因为当我进行单元测试时,我可以简单地调用模拟env。httpHandler


但是,我的问题是...假设您有:


method := e.httpHandler

有没有办法在已经存储到反射或其他东西之后动态更改接收器的值?我可以更改传入的参数,但似乎接收器值已锁定,更改接收器的唯一方法是执行 。在我的情况下,这是不可能的,因为我是从多路复用器路由器中提取的,我只想在呼叫之前换出不同的接收器。ee.httpHandlermethodmethod()e2.httpHandlere.httpHandlerehttpHandler


对于更多的上下文,我基本上用来做表驱动的测试,其中我循环访问每个路由,调用处理程序,检查返回的响应是否是正确的形状,等等。但是,某些路由需要的数据库模拟与其他路由略有不同,因此对路由器中的所有路由使用一刀切的模拟接收器并不理想。我想将处理程序接收器与选定处理程序的自定义模拟环境动态交换。router.Walk()


猛跑小猪
浏览 84回答 2
2回答

万千封印

这是我的想法。你觉得怎么样?type Env struct{    db string // should be database, just example}func (e *Env) httpHandler(w http.ResponseWriter, r * http.Request) {}// In case, create different router by different database.func newRouter(db string) *mux.Router {    e := &Env{        db:db,    }    router := mux.NewRouter()    router.HandleFunc("/foo", e.httpHandler)    router.HandleFunc("/bar", e.httpHandler)    return router}func TestByDatabaseA(t *testing.T)  {    r := newRouter("foo")    r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {        tpl, _ := route.GetPathTemplate()        if !strings.HasPrefix(tpl,"/foo"){            return nil        }        // run test        return nil    })}func TestByDatabaseB(t *testing.T)  {    r := newRouter("bar")    r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {        tpl, _ := route.GetPathTemplate()        if !strings.HasPrefix(tpl,"/bar"){            return nil        }        // run test        return nil    })}

元芳怎么了

如果在测试套件的整个生命周期内需要单个路由器 - 并且由于您无法更改指针接收器或重新注册路由处理程序 - 则可以尝试包装以后可以更改处理程序函数的位置:HandlerFunctype wrapperHandler struct {    Fn http.HandlerFunc}func (wh *wrapperHandler) HandlerFunc() http.HandlerFunc {    return func(w http.ResponseWriter, r *http.Request) {        wh.Fn.ServeHTTP(w, r) // can change `Fn` later    }}使用:// setuprouter := mux.NewRouter()wh := wrapperHandler{} // fill in wh.Fn laterrouter.HandleFunc("/foo", wh.HandlerFunc())e := Env{ /*db1*/ }wh.Fn = e.httpHandlerrunTest(router)e = Env{ /*db2*/ }wh.Fn = e.httpHandlerrunTest(router)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go