golang gorilla/mux和测试,路由应该存储在哪里?

huangapple go评论82阅读模式
英文:

golang gorilla/mux and testing, where to store routes

问题

在我看过的大部分文档中,建议使用gorilla mux的方式如下:

func main() {
    m := mux.Router()
    m.HandleFunc("/", FuncNameOrDef)
    http.ListenAndServe(":8080", m)
}

这样做很好,但是这给我留下了一个问题,因为根据我所见,为了进行测试,我需要重新声明mux和路由,除非我在函数外部声明mux和路由,像这样:

var (
    m = mux.Router()
    _ = m.HandleFunc("/", FuncNameOrDef)
)

然后在我的测试中这样做:

func TestSomeView(t *testing.T) {
    ts := httptest.NewServer(m)
    // 进行测试
}

这解决了问题,但是这样会使包看起来相当丑陋(有很多_ = m.HandleFunc)。有没有更符合惯例的方法来做这个?

英文:

In most of the docs I have seen, gorilla mux is suggested to be used like so...

func main() {
    m := mux.Router()
    m.HandleFunc("/", FuncNameOrDef)
    http.ListenAndServe(":8080", m)
}

which is great, but it leaves me with a problem, because then in order to test, as far as I can see, I need to redeclare mux and routes unless I declare mux and routes outside of a function like this...

var (
    m = mux.Router()
    _ = m.HandleFunc("/", FuncNameOrDef)
)

and then in my tests do this...

func TestSomeView(t *testing.T) {
    ts := httptest.NewServer(m)
    ....testing blah
}

which solves the problem, but then it makes the package pretty ugly (with all the _ = m.HandleFunc's) Is there a more idiomatic way to do this?

答案1

得分: 4

你可以使用一个工厂函数来为你的应用程序创建一个新的http.Handler。这样可以让你以编程方式定义处理程序,并在测试中重用它们。

// NewApplicationHandler为应用程序提供一个配置好的处理程序。
func NewApplicationHandler() http.Handler {
    mux := mux.NewRouter()
    mux.HandleFunc("/", handler)

    return mux
}

func handler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello World!"))
}

这个示例可以在测试中这样使用:

func TestApplicationServeMux(t *testing.T) {
    // 通过调用工厂函数获取处理程序。
    applicationHandler := NewApplicationHandler()

    ts := httptest.NewServer(applicationHandler)
    defer ts.Close()

    res, err := http.Get(ts.URL)

    if err != nil {
        t.Fatalf("%s", err)
    }

    defer res.Body.Close()
    greeting, err := ioutil.ReadAll(res.Body)

    if err != nil {
        log.Fatalf("%s", err)
    }

    want := []byte("Hello World!")

    if !bytes.Equal(want, greeting) {
        t.Errorf("Expected greeting %s; got %s", want, greeting)
    }

}
英文:

You could use a factory function to create a new http.Handler for you application. This would allow you to programmatically define the handlers and reuse them in the tests.

// NewApplicationHandler provides a configured handler for the
// application.
func NewApplicationHandler() http.Handler {
	mux := mux.NewRouter()
	mux.HandleFunc("/", handler)

	return mux
}

func handler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello World!"))
}

This example would be utilized in a test like so:

func TestApplicationServeMux(t *testing.T) {
    // The handlers are being obtained via a call to the factory function.
	applicationHandler := NewApplicationHandler()

	ts := httptest.NewServer(applicationHandler)
	defer ts.Close()

	res, err := http.Get(ts.URL)

	if err != nil {
		t.Fatalf("%s", err)
	}

	defer res.Body.Close()
	greeting, err := ioutil.ReadAll(res.Body)

	if err != nil {
		log.Fatalf("%s", err)
	}

	want := []byte("Hello World!")

	if !bytes.Equal(want, greeting) {
		t.Errorf("Expected greeting %s; got %s", want, greeting)
	}

}

huangapple
  • 本文由 发表于 2017年3月5日 15:21:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/42605649.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定