为了账号安全,请及时绑定邮箱和手机立即绑定

如何动态更改方法接收器

如何动态更改方法接收器

Go
猛跑小猪 2022-10-04 15:50:27
我最近了解到你可以在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()
查看完整描述

2 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

这是我的想法。你觉得怎么样?


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

    })

}


查看完整回答
反对 回复 2022-10-04
?
元芳怎么了

TA贡献1798条经验 获得超7个赞

如果在测试套件的整个生命周期内需要单个路由器 - 并且由于您无法更改指针接收器或重新注册路由处理程序 - 则可以尝试包装以后可以更改处理程序函数的位置:HandlerFunc


type 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

    }

}

使用:


// setup

router := mux.NewRouter()

wh := wrapperHandler{} // fill in wh.Fn later

router.HandleFunc("/foo", wh.HandlerFunc())


e := Env{ /*db1*/ }

wh.Fn = e.httpHandler

runTest(router)


e = Env{ /*db2*/ }

wh.Fn = e.httpHandler

runTest(router)


查看完整回答
反对 回复 2022-10-04
  • 2 回答
  • 0 关注
  • 83 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信