英文:
Resetting http handlers in golang for unit testing
问题
我正在测试一个使用Go语言编写的HTTP服务器,除了一个令人讨厌的问题外,一切都很顺利。
在配置服务器之前,我使用http.Handle("/", myrouter)
注册了一个处理程序,然后在执行http.ListenAndServe
之前,出现了以下问题:
> panic: http: multiple registrations for / [recovered]
我希望在每个测试中都在一个干净的环境中运行,但是我找不到一种方法来清除http.DefaultServeMux
,是否有一种方便的方法可以通过“nulling”某些内容或重新配置测试环境,以便每个测试都在一个新的环境中执行?
编辑:
为了提供一些上下文,如要求的,我在这里发布一些代码和我想编写的测试,但是我必须明确一点,我对这里的实现选择甚至不确定(我认为我会以稍微不同的方式配置服务器,但这不是我的代码)。
package httpserver
import (
"github.com/gorilla/mux"
"github.com/private/private/httpserver/rpchandler"
"net/http"
)
type HTTPServer struct {
router *mux.Router
port int
}
// Config is used to override the default port of the http server.
type Config struct {
Port *int
}
func NewHTTPServer(config *Config) (*HTTPServer, error) {
hs := &HTTPServer{
port: 80,
}
// Overwrite default port if passed.
if config != nil && config.Port != nil {
hs.port = *config.Port
}
err := hs.router = mux.NewRouter().StrictSlash(false)
if err != nil {
return nil, err
}
// 其他mux路由器配置...
http.Handle("/", hs.router)
return hs, nil
}
现在,我想编写的测试非常简单,例如:
func TestThatServerIsInitializedWithDefaultPort(t *testing.T) {
sut, _ := NewHTTPServer(nil)
if sut.port != 80 {
t.Fatal("未配置默认端口")
}
}
func TestThatServerDefaultPortIsOverriddenWithConfig(t *testing.T) {
mockPort := 8080
c := Config{
Port: &mockPort,
}
sut, _ := NewHTTPServer(&c)
if sut.port != 8080 {
t.Fatal("端口未被配置为传入的配置值")
}
}
然而,由于我在http
上调用了两次处理绑定,所以会出现panic。
英文:
I'm testing an http server in golang and everything seems pretty smooth except for one annoying thing.
At some point, when I'm configuring the server, before performing a http.ListenAndServe
I register an handler with http.Handle("/", myrouter)
, the problem is that on the following test, when the configuration method gets called again, I receive the following panic:
> panic: http: multiple registrations for / [recovered]
I'd like to run each test in a clean environment, but haven't found a way to tear down http.DefaultServeMux
, is there a convenient way for doing this by either "nulling" something or re-configuring the test environment so every test is executed on a fresh environment ?
Edit:
To give some context, as asked, I post here some code and the test I wanted to write, I have to be clear tough on the fact that I'm not even sure on the implementation choices made here (I think I would have configured the server in a slightly different way, but the code's not mine).
package httpserver
import (
"github.com/gorilla/mux"
"github.com/private/private/httpserver/rpchandler"
"net/http"
)
type HTTPServer struct {
router *mux.Router
port int
}
// Config is used to override the default port of the http server.
type Config struct {
Port *int
}
func NewHTTPServer(config *Config) (*HTTPServer, error) {
hs := &HTTPServer{
port: 80,
}
// Overwrite default port if passed.
if config != nil && config.Port != nil {
hs.port = *config.Port
}
err := hs.router = mux.NewRouter().StrictSlash(false)
if err != nil {
return nil, err
}
// other mux router configs here...
http.Handle("/", hs.router)
return hs, nil
}
Now, the tests I wanted to write were quite simple, like:
func TestThatServerIsInitializedWithDefaultPort(t *testing.T) {
sut, _ := NewHTTPServer(nil)
if sut.port != 80 {
t.Fatal("default port not configured")
}
}
func TestThatServerDefaultPortIsOverriddenWithConfig(t *testing.T) {
mockPort := 8080
c := Config{
Port: &mockPort,
}
sut, _ := NewHTTPServer(&c)
if sut.port != 8080 {
t.Fatal("the port has not been overridden with the one passed in configuration")
}
}
However, since I call the handle binding on http
twice, I get the panic.
答案1
得分: 5
我认为我找到了一个解决方案:基本上,在每次测试之后,我使用http.DefaultServeMux = new(http.ServeMux)
重新初始化http.DefaultServeMux
。
不过,我还不确定这是否是一种干净的解决方法。
我想请你给我一些提示,或指出我在这里使用的一些不良实践,因为我对这门语言和后端开发都还很陌生。
我认为上面显示的HTTP服务器配置中可能存在一些代码异味,如果你指出来,我可以向我的团队明确,并找到一个更好的解决方案。
英文:
I think I've found a solution: basically after each test I reinitialize http.DefaultServeMux
with http.DefaultServeMux = new(http.ServeMux)
I'm still not sure this is a clean way to workaround the problem tough.
I kindly ask you to give me any hints or point me some bad practices used here, since I'm quite new to the language and to backend development in general.
I think there might be some code smell in the configuration of the HTTP Server shown above, if you point it out I might make it clear to the rest of my team and work a better solution out.
答案2
得分: 0
我认为你应该考虑使用httptest包。它提供了可以在每次测试时重新启动的服务器。
英文:
I think you should look at using the httptest pkg. It has servers that you can start fresh every test.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论