如何在模拟生成中避免导入周期?

时间:2018-06-22 10:41:39

标签: go

简单的例子。

我有包裹xxx。该软件包包含:

  • 结构A
  • 接口B,它是A的字段
  • 结构C,它是B方法中的参数

    type A struct {
        SomeField B
    }
    
    type B interface {
        SomeMethod(c C)
    }
    

现在假设我想为结构A和模拟依赖项B创建单元测试。为创建模拟,我正在使用模拟生成器。所有模拟都存储在公用的“ mocks”文件夹中。

问题是生成的模拟对xxx包具有依赖性。发生这种情况是因为接口B的SomeMethod具有参数xxx.C。

每当我尝试在a_test.go中导入我的模拟结构时,由于循环导入问题,它就会失败。 xxx程序包在a_test.go中导入了模拟程序包。和模拟程序包会在我生成的模拟程序中导入xxx程序包。

我需要一些建议,最好的解决方法是什么?也许我的方法不够习惯。您将模拟物存储在哪里?

3 个答案:

答案 0 :(得分:0)

使用所有其他软件包都从其导入的顶级软件包。将您的界面放在这里。

例如:

domain/
    interfaces.go
a/
    mock.go
b/
    mock.go
c/
    mock.go

abc应该从domain导入,因此它们彼此之间没有任何依赖关系。您将使用鸭子类型在模拟中实现domain包的接口。

这是使用您的示例的实际用例:

domain / interfaces.go

type A interface {
    Foo()
}

type B interface {
    Bar() string
}

type C interface {
    Baz() string
}

a / mock.go

type A struct {
    SomeField domain.B
}

// ...

b / mock.go

type B struct {
    SomeMethod(c domain.C)
}

// ...

c / mock.go

type C struct {}

// ...

那应该可以编译,因为所有模拟都从顶级domain包中导入,并且它们都实现了各自的接口。

答案 1 :(得分:0)

您需要将测试放在其他程序包下。

a.go位于软件包xxx

a_test.go位于软件包xxx_test

a_mock.go位于软件包xxx_mock

通过这种方式a_test.go将依赖于xxxxxx_mock,并且不会导致依赖周期。

此外,a.goa_test.go可以位于同一文件夹下,如下所示:

xxx/
  - a.go
  - a_test.go
mock/
  - a_mock.go

答案 2 :(得分:0)

因为

  1. 界面
  2. 结构
  3. 用户代码
  4. 对用户代码进行单元测试

都在同一个包中,该接口应被视为“包内”接口,对于其他包中的代码而言,该接口不可见。因此,该接口的模拟应该与接口本身位于同一包中。

结论:

  1. 界面
  2. 结构
  3. 用户代码
  4. 对用户代码进行单元测试
  5. 模拟界面

将所有内容都放入同一包装中。

因此,将gomock生成的模拟代码放入与接口相同的程序包中,而不是放入“ mock”程序包中。示例(Windows版本):

mockgen -source=.\foo\bar.go -destination=.\foo\bar_mock.go -package=foo