【问题标题】:How should I unit test middleware packages with gorilla context我应该如何使用 gorilla 上下文对中间件包进行单元测试
【发布时间】:2016-05-12 00:15:38
【问题描述】:

我有这个 net/http 服务器设置,其中包含多个中间件,但我找不到有关如何测试这些中间件的示例...

我在 gorilla/mux 路由器上使用基本的 net/http,一个 Handle 看起来有点像这样:

r.Handle("/documents", addCors(checkAPIKey(getDocuments(sendJSON)))).Methods("GET")

在这些数据中,我汇总了一些数据并通过 Gorilla Context context.Set 方法提供它们。

通常我用 httptest 测试我的 http 函数,我也希望用这些来做,但我不知道怎么做,我很好奇什么是最好的方法。我应该单独测试每个中间件吗?我应该在需要时预先填充适当的上下文值吗?我可以一次测试整个链,以便只检查输入的所需状态吗?

【问题讨论】:

    标签: testing go


    【解决方案1】:

    我不会测试任何涉及 Gorilla 或任何其他 3rd 方包的东西。如果您想测试以确保它正常工作,我会为您的应用程序的运行版本(例如 C.I. 服务器)的端点设置一些外部测试运行程序或集成套件。

    相反,单独测试您的中间件和处理程序 - 就像您可以控制的那样。

    但是,如果您准备测试堆栈(mux -> handler -> handler -> handler -> MyHandler),那么使用 functions as vars 全局定义中间件可能会有所帮助:

    var addCors = func(h http.Handler) http.Handler {
      ...
    }
    
    var checkAPIKey = func(h http.Handler) http.Handler {
      ...
    }
    

    在正常使用期间,它们的实现保持不变。

    r.Handle("/documents", addCors(checkAPIKey(getDocuments(sendJSON)))).Methods("GET")
    

    但对于单元测试,您可以覆盖它们:

    // important to keep the same package name for
    // your test file, so you can get to the private
    // vars.
    package main
    
    import (
      "testing"
    )
    
    func TestXYZHandler(t *testing.T) {
    
      // save the state, so you can restore at the end
      addCorsBefore := addCors
      checkAPIKeyBefore := checkAPIKey
    
      // override with whatever customization you want
      addCors = func(h http.Handler) http.Handler {
        return h
      }
      checkAPIKey = func(h http.Handler) http.Handler {
        return h
      }
    
      // arrange, test, assert, etc.
      //
    
      // when done, be a good dev and restore the global state
      addCors = addCorsBefore
      checkAPIKey = checkAPIKeyBefore
    }
    

    如果您发现自己经常复制粘贴此样板代码,请将其移至单元测试中的全局模式:

    package main
    
    import (
      "testing"
    )
    
    var (
      addCorsBefore = addCors
      checkAPIKeyBefore = checkAPIKey
    )
    
    func clearMiddleware() {
      addCors = func(h http.Handler) http.Handler {
        return h
      }
      checkAPIKey = func(h http.Handler) http.Handler {
        return h
      }
    }
    
    func restoreMiddleware() {
      addCors = addCorsBefore
      checkAPIKey = checkAPIKeyBefore
    }
    
    func TestXYZHandler(t *testing.T) {
    
      clearMiddleware()
    
      // arrange, test, assert, etc.
      //
    
      restoreMiddleware()
    }
    

    关于单元测试端点的附注...

    由于中间件应该以合理的默认值运行(预计正常传递,而不是您要在 func 中测试的底层数据流的互斥状态),我建议在实际主 Handler 函数的上下文之外对中间件进行单元测试.

    这样,您就有了一组严格针对中间件的单元测试。另一组测试完全专注于您正在调用的 url 的主要处理程序。它使新手更容易发现代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-22
      • 1970-01-01
      • 2019-11-28
      • 1970-01-01
      • 2017-04-30
      • 1970-01-01
      • 2020-09-30
      • 2020-11-06
      相关资源
      最近更新 更多