我正在尝试为我已经创建的 REST API 编写不错单元测试。我有这个简单的结构:
ROOT/
config/
handlers/
lib/
models/
router/
main.go
config
包含 JSON 格式的配置和一个简单的 config.go
,它读取和解析 JSON 文件并填充 Config
结构。 handlers
包含 controllers(即 router/routes.go
中描述的相应 METHOD+URL 的处理程序)。 lib
包含一些数据库、请求响应器和记录器逻辑。 models
包含要从 JSON 和 DB 映射到的结构及其函数。最后 router
包含路由器和路由定义。
现在我正在搜索和阅读很多关于在 GO 中对 REST API 进行单元测试的文章,并找到了关于如何设置测试服务器、定义路由和测试我的请求的或多或少令人满意的文章。一切都很好。 但仅当您想要测试单个文件时!
我现在的问题是如何为所有处理程序设置测试环境(服务器、路由、数据库连接)?用找到的方法here (我发现这很容易理解和实现)我有一个问题:我必须为每个处理程序单独运行测试,或者我必须在一个测试中为所有处理程序编写测试套件文件。我相信你明白这两种情况都不是很高兴(第一种是因为我需要保留运行 go test
运行所有成功的测试,第二种是因为拥有一个测试文件来覆盖所有处理程序函数将变得无法维护) .
到目前为止,我已经成功了(根据 the linked article )只有当我将所有测试和初始化代码放入每个 XYZhandler_test.go
文件的一个 func 时,但我也不喜欢这种方法.
我想要实现的是一种 setUp()
或 init()
运行一次,第一次触发测试使所有必需的变量全局可见并初始化,以便所有接下来的测试都可以使用它们,而无需再次实例化它们,同时确保此设置文件仅为测试编译...
我不确定这是否完全清楚,或者这类问题是否需要一些代码示例(除了 already linked in the article,但我会添加您认为需要的任何内容,请告诉我!
最佳答案
测试包,而不是文件!
由于您正在测试处理程序/端点,因此将所有 _test
文件放在处理程序或路由器包中是有意义的。 (例如,每个端点/处理程序一个文件)。
此外,不要使用 init()
来设置您的测试。 testing
包指定具有以下签名的函数:
func TestMain(m *testing.M)
The generated test will call TestMain(m) instead of running the tests directly. TestMain runs in the main goroutine and can do whatever setup and teardown is necessary around a call to m.Run. It should then call os.Exit with the result of m.Run
在 TestMain 函数中,您可以进行任何需要的设置以运行测试。如果你有全局变量,这是声明和初始化它们的地方。您只需要为每个包执行一次此操作,因此将 TestMain
代码放在单独的 _test
文件中是有意义的。例如:
package router
import (
"testing"
"net/http/httptest"
)
var (
testServer *httptest.Server
)
func TestMain(m *testing.M) {
// setup the test server
router := ConfigureRouter()
testServer = httptest.NewServer(router)
// run tests
os.Exit(m.Run())
}
最后使用 go test my/package/router
运行测试。
关于api - GO单元测试结构化REST API项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36177614/