【问题标题】:import cycle in golang with test packages带有测试包的golang中的导入周期
【发布时间】:2018-03-11 14:16:34
【问题描述】:

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

一些细节,我有三个包:testutilsclientengine

在引擎中,我定义了一个接口和实现(均已导出)。

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 注释中将该方法标识为测试实用程序即可。退一步说,你为什么需要不同于生产的测试的初始化逻辑?

标签: testing go


【解决方案1】:

您可以使用黑盒样式测试,因为引擎的组件是导出的。将您的测试更改为 package engine_test:

package engine_test
import "engine"
import "testutils"
func TestMain(m *testing.M) {
  e, err := testutils.CreateAndConnect()
  // ....
  os.Exit(m.Run())
}

【讨论】:

    猜你喜欢
    • 2019-03-30
    • 1970-01-01
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    • 2018-01-18
    • 2022-07-13
    相关资源
    最近更新 更多