在使用测试包的情况下,Golang中的导入循环问题

4

我正在尝试重构一些测试代码,在两个包中我需要做同样的事情(连接到数据库)。我遇到了一个导入循环的问题。我明白为什么不能这样做,但想知道最好的解决方法是什么。

具体来说,我有三个包:testutilsclientengine

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_test.go上的导出方法,并在client/client_test.go中使用它。但没有成功。:/
我感觉我在其他语言中也做过这件事,但可能是我自己疯了。如何为可重用性构建此代码的最佳方式?

1
为什么CreateAndConnect()函数不能存在于引擎包中? - Michael Whatcott
这只是一个测试方法,它会加载测试配置和测试数据库。 - rybit
但是我无法在另一个包的测试中导入它。 - rybit
这里需要多少逻辑?一些复制/粘贴可能没问题。或者你可以将CreateAndConnect()函数放在引擎包中,以便其他包可以导出它。然后只需在其godoc注释中标识该方法为测试实用程序即可。退一步说,为什么测试需要与生产不同的初始化逻辑呢? - Michael Whatcott
我们通过创建只用于保存测试工具的包来解决这个问题。只需给它们起一个明显的名称,以便没有人会在非测试代码中使用它们。 - Endophage
显示剩余3条评论
1个回答

4
你可以使用黑盒测试的方式,因为引擎的组件是被导出的。将你的测试更改为在engine_test包中进行:
package engine_test
import "engine"
import "testutils"
func TestMain(m *testing.M) {
  e, err := testutils.CreateAndConnect()
  // ....
  os.Exit(m.Run())
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接