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

如何在 go 中使用马提尼测试反向代理

如何在 go 中使用马提尼测试反向代理

Go
一只萌萌小番薯 2021-11-22 20:05:32
我正在为在 go 中作为反向代理工作的 martini 应用程序编写测试代码,并想使用 测试它httptest.ResponseRecorder,但出现以下错误。[martini] PANIC: interface conversion: *httptest.ResponseRecorder is not http.CloseNotifier: missing method CloseNotifyhttptest.ResponseRecorder 没有方法 CloseNotify()我应该如何测试?package mainimport (        "github.com/go-martini/martini"        "github.com/stretchr/testify/assert"        "net/http"        "net/http/httptest"        "net/http/httputil"        "net/url"        "testing")func TestReverseProxy(t *testing.T) {        // Mock backend        backendResponse := "I am the backend"        backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {                w.Write([]byte(backendResponse))        }))        defer backend.Close()        backendURL, _ := url.Parse(backend.URL)        // Frontend        m := martini.Classic()        m.Get("/", func(w http.ResponseWriter, r *http.Request) {                proxy := httputil.NewSingleHostReverseProxy(backendURL)                proxy.ServeHTTP(w, r)        })        // Testing        req, _ := http.NewRequest("GET", "/", nil)        res := httptest.NewRecorder()        m.ServeHTTP(res, req)        assert.Equal(t, 200, res.Code, "should be equal")}
查看完整描述

1 回答

?
慕森王

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

首先,请注意 martini 框架不再像他们的README 中所说的那样维护。


然后,关于您的问题,这是因为 Martini 做了一些对我来说看起来很糟糕的事情:它需要一个http.ResponseWriter并假设它也是一个http.CloseNotifier,而绝对不能保证这一点。他们应该采用一个自定义界面来包装它们,如下所示:


type ResponseWriterCloseNotifier interface {

    http.ResponseWriter

    http.CloseNotifier

}

您可以在他们的源代码中看到他们在自己的测试中遇到了同样的问题,并使用了一些解决方法:https : //github.com/go-martini/martini/commit/063dfcd8b0f64f4e2c97f0bc27fa422969baa23b#L13


这是一些用它制作的工作代码:


package main


import (

    "net/http"

    "net/http/httptest"

    "net/http/httputil"

    "net/url"

    "testing"


    "github.com/go-martini/martini"

    "github.com/stretchr/testify/assert"

)


type closeNotifyingRecorder struct {

    *httptest.ResponseRecorder

    closed chan bool

}


func newCloseNotifyingRecorder() *closeNotifyingRecorder {

    return &closeNotifyingRecorder{

        httptest.NewRecorder(),

        make(chan bool, 1),

    }

}


func (c *closeNotifyingRecorder) close() {

    c.closed <- true

}


func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {

    return c.closed

}


func TestReverseProxy(t *testing.T) {

    // Mock backend

    backendResponse := "I am the backend"

    backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        w.Write([]byte(backendResponse))

    }))

    defer backend.Close()

    backendURL, _ := url.Parse(backend.URL)


    // Frontend

    m := martini.Classic()

    m.Get("/", func(w http.ResponseWriter, r *http.Request) {

        proxy := httputil.NewSingleHostReverseProxy(backendURL)

        proxy.ServeHTTP(w, r)

    })


    // Testing

    req, _ := http.NewRequest("GET", "/", nil)

    res := newCloseNotifyingRecorder()

    m.ServeHTTP(res, req)


    assert.Equal(t, 200, res.Code, "should be equal")

}


查看完整回答
反对 回复 2021-11-22
  • 1 回答
  • 0 关注
  • 151 浏览
慕课专栏
更多

添加回答

举报

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