gpt4 book ai didi

unit-testing - 如何测试/重构测试调用 http.ListenAndServe 的函数

转载 作者:数据小太阳 更新时间:2023-10-29 03:08:58 25 4
gpt4 key购买 nike

我正在学习 go 并且正在开发一个简单的服务,该服务从队列中提取一些数据并将其保存在数据库中。它还运行一个网络服务器以允许抓取数据。现在我有两个 go 文件(为简洁起见省略了一些文本):

func main() {
parseConfig()

s := &Service{ServiceConfig: config}
err := s.Run()
if err != nil {
panic(err)
}
}

然后是服务的定义(为简洁起见,再次省略了一些部分):

func (s *Service) Run() error {

if err := s.validate(); err != nil {
return err
}

if err := s.initDB(); err != nil {
return err
}
defer s.db.Close()

// Same pattern with health check library (init, start, close)
// Same pattern starting queue consumer (init, start, close)

s.mux = http.NewServeMux()
s.registerHandlers(s.mux)

http.ListenAndServe(":8080", s.mux)

return nil
}

和结构

type Service struct {
Config // Hold db connection info
db *sql.DB
hc *health
}

我能够很好地测试各个部分(如 initDBvalidate),但我不清楚如何测试 Run 函数因为 http.ListenAndServe block 。我最终超时了。以前,我会使用 httpTest 并制作一个测试服务器,但那是 main 启动服务器的时候(应用程序起初更基本)。

我要测试的一些东西:

一旦开始,我就可以达到指标端点。一旦开始,我就可以达到健康终点。我可以在队列中推送一条消息,一旦启动就会收到。Run 实际上是在没有 panic 的情况下开始的。

一些注意事项:我正在使用 docker 启动队列和数据库。测试 Run 函数的目的是确保引导工作正常并且应用程序可以成功运行。最终我会想要通过队列推送数据并断言它已被正确处理。

问题:我应该如何测试或重构它,以便端到端更容易测试?

最佳答案

您可以使用 goroutine 构建测试工具以在单元测试中执行 Run:

func TestRun(t *testing.T) {
service := Service{}
serviceRunning := make(chan struct{})
serviceDone := make(chan struct{})
go func() {
close(serviceRunning)
err := service.Run()
defer close(serviceDone)
}()

// wait until the goroutine started to run (1)
<-serviceRunning

//
// interact with your service to test whatever you want
//

// stop the service (2)
service.Shutdown()

// wait until the service is shutdown (3)
<-serviceDone
}

这只是一个基本示例,用于说明原则上如何完成。有几点需要改进才能用于生产:

(0) 最重要的细节:不要在生产中使用 http.ListenAndServe! 创建您自己的 http.Server 实例.这样可以省去很多麻烦。

s.httpServer := http.Server {
Addr: ":8080",
Handler: s.mux,
}

(1) 服务正在运行的指示应该移到您的 Service 类型中。 Run 中的初始化部分可能需要一段时间,并且应在调用 ListenAndServe 之前关闭指示 channel :

close(s.Running)
s.httpServer.ListenAndServe()

当然,您需要在您的服务类型中添加指示 channel 。

(2) 向调用s.httpServer.Shutdown()Service 添加一个Shutdown 方法。这将导致对 s.httpServer.ListenAndServe 的调用返回错误 http.ErrServerClosed

if err := s.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
return err
}
return nil

在测试结束时关闭您的服务很重要。否则,您将无法为您的服务进行多个单元测试。无论如何,清理资源是一个好公民。

(3) 您需要等到 service.Run 返回以确保服务确实已关闭。

关于unit-testing - 如何测试/重构测试调用 http.ListenAndServe 的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55699470/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com