【问题标题】:How can I unit test Google App Engine Go HTTP handlers?如何对 Google App Engine Go HTTP 处理程序进行单元测试?
【发布时间】:2013-10-24 19:10:57
【问题描述】:

本地单元测试是来自 Google App Engine Go SDK 1.8.6 版的supportedappengine/aetest 包允许我创建一个 Context 来进行单元测试。

如何将它与 net/http/httptest 一起使用来测试我的 HTTP 处理程序?

【问题讨论】:

    标签: google-app-engine unit-testing go


    【解决方案1】:

    如果你不反对使用Martini,依赖注入是解决问题的好方法。以下是设置测试的方法(使用Ginkgo):

    var _ = Describe("Items", func() {
    
        var (
            m *martini.ClassicMartini
        )
    
        BeforeEach(func() {
            m = martini.Classic()
    
            // injects app engine context into requests
            m.Use(func(c martini.Context, req *http.Request) {
                 con, _ := aetest.NewContext(nil)
                 c.MapTo(con, (*appengine.Context)(nil))
            })
    
            m.Get("/items", func(c martini.Context){
                 // code you want to test
            })
        })
    
        It("should get items", func() {
            recorder := httptest.NewRecorder()
            r, _ := http.NewRequest("GET", "/items", nil)
            m.ServeHTTP(recorder, r) // martini server used
            Expect(recorder.Code).To(Equal(200))
        })
    })
    

    在生产中,实际的上下文将被注入:

    m.Use(func(c martini.Context, req *http.Request) {
        c.MapTo(appengine.NewContext(req), (*appengine.Context)(nil))
    })
    

    【讨论】:

      【解决方案2】:

      查看 goroot/src/pkg/appengine/aetest/context.go 的顶部(更新的源代码尚未发布在 https://code.google.com/p/appengine-go)。乍一看,新的测试应用程序看起来是appenginetesting 的一个稍微强大/不同的版本,因此您可以进行相同类型的测试,请参阅here 了解如何使用 sampleHandler(w http.ResponseWriter, r *http.Request) 被调用。

      或者,您可以使您的 http.Handler 的 ContextHandler 如下所示:

      type ContextHandler struct {
          Real func(*appengine.Context, http.ResponseWriter, *http.Request)
      }
      
      func (f ContextHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
          c := appengine.NewContext(r)
          f.Real(c, w, r)
      }
      
      func myNewHandler(c appengine.Context, w http.ResponseWriter, r *http.Request) {
      // do something
      }
      

      然后你可以在 init() 中这样做来支持生产:

      http.Handle("/myNewHandler", ContextHandler{myNewHandler})
      

      这使得测试函数变得容易:

      func TestMyNewHandler(t *testing.T) {
          c := aetest.NewContext()
          r, _ := http.NewRequest("GET", "/tasks/findOverdueSchedules", nil)
          w := httptest.NewRecorder()
          myNewHandler(c, w, r)
          if 200 != w.Code {
              t.Fail()
          }
      }
      

      以下是 appengine/aetest 中 context.go 的内容:

      /* 包 aetest 提供了一个 appengine.Context 用于测试。

      一个示例测试文件: 包 foo_test

      import (
          "testing"
      
          "appengine/memcache"
          "appengine/aetest"
      )
      
      func TestFoo(t *testing.T) {
          c, err := aetest.NewContext(nil)
          if err != nil {
              t.Fatal(err)
          }
          defer c.Close()
      
          it := &memcache.Item{
              Key:   "some-key",
              Value: []byte("some-value"),
          }
          err = memcache.Set(c, it)
          if err != nil {
              t.Fatalf("Set err: %v", err)
          }
          it, err = memcache.Get(c, "some-key")
          if err != nil {
              t.Fatalf("Get err: %v; want no error", err)
          }
          if g, w := string(it.Value), "some-value" ; g != w {
              t.Errorf("retrieved Item.Value = %q, want %q", g, w)
          }
      }
      

      环境变量 APPENGINE_API_SERVER 指定了 要使用的 api_server.py 可执行文件。如果未设置,则查询系统 PATH。 */

      【讨论】:

      • 在所有非测试代码处理程序中都有var contextCreator func(r *http.Request) appengine.Context = appengine.NewContext (github.com/icub3d/appenginetesting/blob/master/…) 似乎不太优雅。
      • 在每个 http.Handler 中都有 c := appengine.NewContext(r) 似乎也不优雅。我已经更新了我的帖子,包括我是如何做到的。
      • 我同意你的观点,这似乎是一个很好的解决方案。事实上,我正在使用 Gorilla Toolkit 并稍微抽象了您的示例以使用 github.com/gorilla/context,这使我能够添加与设置请求相关的各种其他内容。
      猜你喜欢
      • 2015-05-04
      • 2021-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多