Run http.ListenAndServe() On Tests using stretchr/testify suite Stop Test From Proceed

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

Run http.ListenAndServe() On Tests using stretchr/testify suite Stop Test From Proceed

问题

我正在尝试为我使用gorilla/muxgorm.iogolang-migrate/v4创建集成测试的REST API应用程序编写集成测试。

对于测试,我正在使用testify

我的integration_Test.go中的SetupSuite()如下所示:

func (s *ReceiptServiceTestSuite) SetupSuite() {
	s.Require().NoError(godotenv.Load("test.env"))
	s.Require().NoError(database.Connect())
	s.db = database.DB
	s.m = database.M

	router.HandleRequests()
}

而我的router.HandleRequests()如下所示:

func HandleRequests() {
	router := mux.NewRouter()
	router.Use(middleware)
    // 大量的router.HandleFunc()
    
    http.ListenAndServe(":8080", router)
}

问题是:如果我从SetupSuite()中移除router.HandleRequests(),所有的数据库测试都能正常运行,但是如果我尝试使用http.ListenAndServe(),测试工作流会停止,什么都不会发生。

我相信我应该使用goroutines和router.HandleRequests(),这样它就可以与测试并行运行,我只是不知道如何做到这一点。

更多信息,请参阅项目repository,我不知道这是否相关,但我正在使用docker-compose运行两个postgres实例,一个用于项目运行,另一个用于测试。

英文:

I'm trying to create integration tests for my REST API application which I made using gorilla/mux, gorm.io and golang-migrate/v4

For the tests I'm using testify.

My SetupSuite() in my integration_Test.go is like this:

func (s *ReceiptServiceTestSuite) SetupSuite() {
	s.Require().NoError(godotenv.Load("test.env"))
	s.Require().NoError(database.Connect())
	s.db = database.DB
	s.m = database.M

	router.HandleRequests()
}

And my router.HandleRequests() is like this:

func HandleRequests() {
	router := mux.NewRouter()
	router.Use(middleware)
    // lots of router.HandleFunc()
    
    http.ListenAndServe(":8080", router)
}

The thing is: if I remove router.HandleRequests() from the SetupSuite(), all my database tests run normally, but if I try to http.ListenAndServe() the test workflow stop and nothing happens.

I believe that I should use goroutines with router.HandleRequests() so it can run parallel with the tests, I just can't figure it out how to do it.

For further information, here is the project repository, and I don't know if it is relevant, but I'm running two postgres instances using docker-compose, one for the project to run and another for the tests.

答案1

得分: 1

我找到了使用Go协程来实现的方法。

我阅读了这个示例,它教你如何使用通道处理os.Signals,我按照以下方式实现了它:

首先,在路由器中进行了以下更改:

func HandleRequests() {
    router := mux.NewRouter()
    router.Use(middleware)
    // 大量的router.HandleFunc()
    
    go http.ListenAndServe(":8080", router)

    quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	<-quit

}

现在,http.ListenAndServe()在一个新的线程中运行。我相信默认情况下,它会在程序执行结束时停止。

http.ListenAndServe()之后,我创建了一个os.Signal通道,用于监听系统发出的信号(SIGINT和SIGTERM),然后函数将在<-quit处停止,等待一个信号继续执行。

然后,我修复了SetupSuite(),在一个goroutine中运行router.HandleRequests()

func (s *ReceiptServiceTestSuite) SetupSuite() {
	s.Require().NoError(godotenv.Load("test.env"))
	s.Require().NoError(database.Connect())
	s.db = database.DB
	s.m = database.M

	go router.HandleRequests()
}

TearDownSuite()中,我向当前进程发送了一个SIGTERM信号,该信号将被我之前在router.HandleRequests()中创建的quit通道监听,然后函数将继续终止程序。

func (s *ReceiptServiceTestSuite) TearDownSuite() {
    // 一些数据库代码
	p, _ := os.FindProcess(os.Getpid())
	p.Signal(syscall.SIGINT)
}
英文:

I figured out how to do it using go routines.

I read this example which teaches how to deal with os.Signals using channels and I implemented it this way:

First, I made the following changes at the router:

func HandleRequests() {
    router := mux.NewRouter()
    router.Use(middleware)
    // lots of router.HandleFunc()
    
    go http.ListenAndServe(&quot;:8080&quot;, router)

    quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	&lt;-quit

}

So now http.ListenAndServe() is running in a new thread. I believe that by a default behavior, it stops at the end of the program execution.

After http.ListenAndServe(), I created a os.Signal chanel which will listen to incomming signals from the system (SIGINT and SIGTERM), then the function will stop at &lt;-quit, which will be wating for one signal to continue.

Then I fixed my SetupSuite() to run router.HandleRequests() in a goroutine:

func (s *ReceiptServiceTestSuite) SetupSuite() {
	s.Require().NoError(godotenv.Load(&quot;test.env&quot;))
	s.Require().NoError(database.Connect())
	s.db = database.DB
	s.m = database.M

	go router.HandleRequests()
}

And at my TearDownSuite() I send a SIGTERM signal to the current process, wich will be listened by the quit channel I've created before at router.HandleRequests() and the function will proceed to terminate the program.

func (s *ReceiptServiceTestSuite) TearDownSuite() {
    // some database code 
	p, _ := os.FindProcess(os.Getpid())
	p.Signal(syscall.SIGINT)
}

huangapple
  • 本文由 发表于 2022年1月28日 09:58:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/70887990.html
匿名

发表评论

匿名网友

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

确定