测试使用 Gorilla/context 的处理程序

Testing handlers that use Gorilla/context

我在网络应用程序中使用 gorilla/context。文档中的示例如下所示:

func MyHandler(w http.ResponseWriter, r *http.Request) {
    //...

    val := context.Get(r, foo.MyKey)

    //...
}

如何对这样工作的处理程序进行单元测试?到目前为止我管理的唯一方法是在我的测试中使用上下文包。我现在在想我可以将一个上下文参数注入到处理程序中,但是我不符合 HandlerFunc 接口。

这是一个经典的cross-cutting concerns例子。

您正在使用第 3 方神奇地处理被测单元的输入参数。根据这个定义,你将不得不做一些额外的设置来为你想要的状态准备 context

当涉及到 Go http 处理程序(惯例是 KISS 它)时,你不需要 "reach out of context" 你的函数来获取额外的数据:将你需要的所有数据保存在你的单一功能

就个人而言,我尽量避免像这样破坏我的处理程序。我想在我建立的几十个大网站中,我只用过一次大猩猩的上下文。这基本上是为了绕过缓存响应,只是为了让最终用户刷新数据。我在单元测试中忽略了其中的内容,因为它超出了我正在测试的范围。

相反,我使用中间件包装器在我的句柄中设置我想要的基础知识并相应地修改处理程序的签名。

  • 缓存
  • 日志记录
  • 认证与授权
  • json 编组
  • 上下文(例如从数据库加载的预期 User{} 对象)

...等当您使用 mux 注册它时,我会创建一个包装您的处理程序的中间件,它使用 gorilla/context 查找您的 cookie 或用户 ID 或其他东西,从缓存、数据库、redis 等中隐藏该用户对象,然后调用您的处理程序,该处理程序的签名如下:

func MyHandler(u User, p Page, w http.ResponseWriter, r *http.Request) {
    // u is the User object loaded from middle-ware

    // p is your global Page object... etc
}

这样,您的单元测试只会注入您需要的测试项目。

并且您可以在 QA 服务器上使用数据存储中的预期用户和页面对象集成测试您的中间件。

我的团队的做法是为路由处理程序添加一个名称,然后在测试中我们按名称调用该路由。

这是添加路线的方法:

r.HandleFunc("/<route>", MyHandler).Methods("GET").Name("MyHandlerByName")

那么这就是测试方法

r.Get("MyHandlerByName")

测试句柄的一种方法是修改句柄的创建方式。例如,创建一个 return a http.HandlerFunc 的函数,这个函数可以有参数。您可以模拟发送给函数的值

无参数

 func State() http.HandlerFunc {
        return http.HandlerFunc(func(pResponse http.ResponseWriter, r *http.Request)    {
            // your code
        })
    }

带参数

   func State(pParam1,pParam2,pParam3 ...) http.HandlerFunc {
        return http.HandlerFunc(func(pResponse http.ResponseWriter, r *http.Request)    {
            // your code using pParam1,pParam2,pParam3 
        })
    }

映射将是

http.HandleFunc("/State", State())

http.HandleFunc("/State", State(value1,value2,value3 ....))