我正在尝试为我已创建的REST API编写 nice 单元测试。我有这个简单的结构:
ROOT/
config/
handlers/
lib/
models/
router/
main.go
config
包含JSON中的配置和一个简单的config.go
,它读取并解析JSON文件并填充Config
结构。 handlers
包含控制器(即router/routes.go
中描述的各个METHOD + URL的处理程序)。 lib
包含一些DB,请求响应器和记录器逻辑。 models
包含要从-JSON和DB映射的结构及其func。最后router
包含路由器和路由定义。
现在我正在搜索和阅读很多关于GO中的REST API的单元测试,并且发现了或多或少令人满意的文章,关于如何设置测试服务器,定义路由和测试我的请求。一切都很好。 但仅当您要测试单个文件时才能使用
我现在的问题是如何为所有处理程序设置测试环境(服务器,路由,数据库连接)?通过找到here的方法(我觉得很容易理解和实现)我有一个问题:我必须为每个处理程序单独运行测试或我必须写仅在一个测试文件中为所有处理程序测试套件。我相信你明白这两种情况都不是很高兴(第一,因为我需要保留运行go test
运行所有成功的测试和第二,因为有一个测试文件覆盖所有处理程序功能将变得不可维护)。
到目前为止,只有当我将所有测试和初始化代码放在每个XYZhandler_test.go
文件的一个函数中时,我才成功(根据the linked article),但我也不喜欢这种方法。
我想要实现的是setUp()
或init()
,它在第一次触发测试时运行一次,使所有必需变量全局可见并初始化,以便所有下一个测试都可以在不需要的情况下使用它们再次实例化它们,同时确保只为测试编译此安装文件...
我不确定这是否完全清楚,或者此类问题是否需要一些代码示例(already linked in the article除外)但我会添加您认为必需的任何内容,请告诉我! / p>
答案 0 :(得分:1)
也许你可以把你想要使用的设置代码从多个单元测试文件放到一个只有单元测试使用的独立包中?
或者您可以将设置代码放入普通包中,只需在单元测试中使用它即可。
以前曾经问过,但Go作者选择不隐式提供可用于在普通包文件中有选择地启用函数编译的测试标记。
答案 1 :(得分:1)
测试包,而不是文件!
由于您正在测试处理程序/端点,因此将所有_test
文件放在处理程序或路由器程序包中是有意义的。 (例如,每个端点/处理程序一个文件)。
另外,请勿使用init()
来设置测试。 testing
包指定具有以下签名的函数:
func TestMain(m *testing.M)
生成的测试将调用TestMain(m)而不是运行测试 直。 TestMain在主goroutine中运行,可以做任何事情 在调用m.Run时,必须进行设置和拆卸。它应该 使用m.Run
的结果调用os.Exit
在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
运行测试。