【发布时间】:2018-03-11 14:16:34
【问题描述】:
我正在尝试重构一些测试代码,并且在两个包中我需要做同样的事情(连接到数据库)。我得到一个导入周期。我明白为什么我不能这样做,但我想知道最好的解决方法是什么。
一些细节,我有三个包:testutils、client、engine。
在引擎中,我定义了一个接口和实现(均已导出)。
package engine
type interface QueryEngine {
// ...
}
type struct MagicEngine {
// ...
}
然后我将在testutils 包中创建一个MagicEngine 并尝试返回它。
package testutils
func CreateAndConnect() (*engine.MagicEngine, error) {
// ....
}
现在在测试代码中(使用TestMain)我需要做类似的事情
package engine
func TestMain(m *testing.M) {
e, err := testutils.CreateAndConnect()
// ....
os.Exit(m.Run())
}
这当然是一个循环。我想这样做,以便我可以在client 包中也使用这个testutils.CreateAndConnect() 方法。我不想在两个包中重复代码。我不希望它出现在 engine 包的主代码中,它对测试非常具体。
我尝试将它作为导出方法添加到 engine 测试类 (engine/engine_test.go) 并在 client/client_test.go 中使用它。没有骰子。 :/
我觉得我已经用其他语言做到了这一点,但可能会很疯狂。构建此代码以实现可重用性的最佳方式是什么?
【问题讨论】:
-
为什么 CreateAndConnect() 函数不能存在于引擎包中?
-
它纯粹是一种测试方法,它围绕加载测试配置和测试数据库做一些事情。
-
所以,你可以把它放在引擎包中,但是放在 *_test.go 文件中。然后它不会被编译成生产二进制文件,你避免了导入周期。
-
但是我不能在另一个包的测试中导入它
-
我们在这里谈论多少逻辑?一点点复制/粘贴可能没问题。或者您可以将 CreateAndConnect() 函数放在引擎包中,以便由其他包导出。然后只需在其 godoc 注释中将该方法标识为测试实用程序即可。退一步说,你为什么需要不同于生产的测试的初始化逻辑?