douhe6181 2016-11-24 12:31
浏览 46
已采纳

重置golang中的http处理程序以进行单元测试

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.

  • 写回答

2条回答 默认 最新

  • douyin2962 2016-11-24 16:05
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计