【问题标题】:Mocking external struct dependencies in golang在 golang 中模拟外部结构依赖项
【发布时间】:2017-02-23 17:45:22
【问题描述】:

我很难找到一种在 golang 中编写可测试代码的惯用方式。我了解接口的重要性及其在测试中的用途,但我还没有弄清楚如何模拟/测试外部结构依赖项。

作为示例,我编写了以下代码,它模拟了在 GitHub 上创建拉取请求的包装器。

type GitHubService interface {

}

type gitHubService struct {
    CreatePullRequest(...) (PullRequest,error)
}

func (s gitHubService) CreatePullRequest(...) (PullRequest,error) {
  tp := github.BasicAuthTransport{
      Username: strings.TrimSpace(/*.....*/),
      Password: strings.TrimSpace(/*.....*/),
    }

    client := github.NewClient(tp.Client())
  pr,err := client.Repositories.CreatePullRequest(...)

  ...
}

func TestPullRequest(t *testing.T) {
  service := gitHubService{}
  pr,err := service.CreatePullRequest(...)
  ...
}

如果我正在为 GitHubService.CreatePullRequest(...) 编写单元测试,我想模拟对 client.Repositories.CreatePullRequest(...) 的调用,甚至可能模拟对 github.NewClient(...) 的调用,以返回我可以控制的模拟实现。

使用诸如gomock 之类的工具,您似乎对结构和包函数不走运。

处理这个问题的惯用方法是什么?我对控制反转以及依赖注入和服务定位器等不同模式非常熟悉,但我无数次听到这不是惯用的。

【问题讨论】:

  • 单元测试应该单独测试CreatePullRequest的逻辑,我对集成测试不感兴趣。
  • 我的意思是这里没有逻辑可以测试——一切都发生在 github 包中,它有自己的测试。如果您确实在 ...s 后面隐藏了其他逻辑,则将其拆分为单独的部分进行测试。
  • @JimB 如果我将... 背后的逻辑拆分为自己的测试,我正在测试这些东西,而不是CreatePullRequest(...) 中的逻辑。我仍然想要一个单元测试来测试这个代码单元的逻辑流。

标签: unit-testing go


【解决方案1】:

Go 的一个重要设计特性是解耦 (Watch this great talk from Bill Kennedy about that topic)。在您的方法内部有一些依赖项,可以解耦。这种耦合方法使其无法真正进行测试。

你应该重构的东西:

  • tp := github.BasicAuthTransport:你不应该在你的方法中初始化授权。它应该作为参数移动到您的 gitHubService 中。在您的方法调用中,您可以通过s.tp 访问ist。您也可以将其作为方法的输入参数。
  • github.NewClient()client.Repositories.CreatePullRequest(...) 只需阅读来自 Peter Bourgon Make dependencies explicit! 的 golang 最佳实践。另一种方法是创建一个接口,其中包含所有被调用的函数。这个接口应该是你方法的输入。

解耦代码后,您可以非常轻松地模拟所有内容。如果您使用接口作为输入,您可以创建一个模拟结构,它实现了接口。如果使依赖项显式化,则可以覆盖它们。在最后一种情况下,用于存储调用值的代码不是那么干净,但它也可以工作。惯用的方式是使用接口。

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,看起来,您唯一的选择是在其间设置另一层,该层将调用您的“不可模拟”客户端。

    例如为了模拟 govmi 客户端(用于 golang 的 vmware 客户端 sdk),我必须有一个具有接口和结构的“myCustomClient”才能调用 govmi.Client.AnyMethod..

    然后我可以为“myCustomClient”生成模拟。

    mockgen -source myCustomClient.go -package myPackage -destination myCustomClientMock.go

    您可以通过以下方式安装它:get get github.com/golang/mock

    【讨论】:

      猜你喜欢
      • 2019-01-18
      • 2018-01-21
      • 1970-01-01
      • 2020-04-14
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多