Golang:如何使用gomock模拟…interface{}参数

huangapple go评论87阅读模式
英文:

Golang: how to mock ...interface{} arguents using gomock

问题

我有一个使用标准go Printf 函数签名的 Printer 接口:

type Printer interface {
    Printf(format string, tokens ...interface{})
}

我想使用 gomock 来模拟这个接口,但是我不确定如何正确设置 tokens ...interface{} 参数。

我原以为 Printf(gomock.Any(), gomock.Any()) 可以覆盖所有可能的情况(因为 tokens 编译为 []interface{}),但是似乎你需要为 N 个 token 设置一个明确的调用:

// 没有 token
mockPrinter.EXPECT().
    Printf(gomock.Any()).
    AnyTimes()

// 1 个 token
mockPrinter.EXPECT().
    Printf(gomock.Any(), gomock.Any()).
    AnyTimes()

// 2 个 token
mockPrinter.EXPECT().
    Printf(gomock.Any(), gomock.Any(), gomock.Any()).
    AnyTimes()

// ... 直到 N 个 token

有人知道有更好的方法吗

<details>
<summary>英文:</summary>

I have a `Printer` interface that uses the standard go `Printf` function signature:

    type Printer interface {
        Printf(format string, tokens ...interface{})
    }

I would like to be able to mock this interface using [gomock](https://github.com/golang/mock), but I&#39;m not sure how setup the `tokens ...interface{}` argument properly. 

I expected that `Printf(gomock.Any(), gomock.Any())` would cover all potential cases (since `tokens` compiles to `[]interface{}`), but it appears you need to setup an explicit call for N number of tokens:

    // no tokens
    mockPrinter.EXPECT().
        Printf(gomock.Any()).
        AnyTimes()

    // 1 token
    mockPrinter.EXPECT().
        Printf(gomock.Any(), gomock.Any()).
        AnyTimes()

    // 2 tokens
    mockPrinter.EXPECT().
        Printf(gomock.Any(), gomock.Any(), gomock.Any()).
        AnyTimes()

    // ... up to N tokens

Does anyone know of a better way to do this?

</details>


# 答案1
**得分**: 2

当前版本的gomock不支持这个功能也许你可以扩展它并发送一个拉取请求要理解为什么不可能你需要查看为可变参数函数生成的模拟

为了做到这一点让我们看一下gomock存储库中的示例特别是[./sample/mock_user/user.go][1][./sample/mock_user/mock_user.go][2]

### 生成的模拟 ###

你会看到*Index*接口中有一个名为*Ellip*的函数类似于你的*Printf*函数

    type Index interface {
        // ...
        Ellip(fmt string, args ...interface{})
        // ...
    }

现在这是*Ellip*的模拟函数的样子

    func (_m *MockIndex) Ellip(_param0 string, _param1 ...interface{}) {
        _s := []interface{}{_param0}
        for _, _x := range _param1 {
            _s = append(_s, _x)
        }
        _m.ctrl.Call(_m, "Ellip", _s...)
    }

注意到什么奇怪的地方了吗gomock创建了一个接口切片**_s**用第一个参数进行初始化然后它将可变参数追加到该接口切片**_s**

所以明确一点它不仅仅是将可变参数**_param1**追加到切片中它通过迭代可变参数**_param1**将每个单独的可变参数追加到新的切片中

这意味着可变参数的切片并没有被保留下来它被拆分了

  [1]: https://github.com/rafrombrc/gomock/blob/9dcd4b2cd01be60f9fbabacce2a6ae1ed21ea48f/sample/user.go
  [2]: https://github.com/rafrombrc/gomock/blob/9dcd4b2cd01be60f9fbabacce2a6ae1ed21ea48f/sample/mock_user/mock_user.go

<details>
<summary>英文:</summary>

Not possible with the current version of gomock. Maybe you can extend it, and send a pull request in. To understand why it&#39;s not possible, you have to look at the mock generated for variadic functions.

To do that, let&#39;s look at the examples in gomock&#39;s repository, specifically [./sample/mock_user/user.go][1] and [./sample/mock_user/mock_user.go][2].

### Generated Mock ###
You&#39;ll see a function in the *Index* inteface called *Ellip*, which is like your *Printf* function:

    type Index interface {
        // ...
        Ellip(fmt string, args ...interface{})
        // ...
    }
Now, here&#39;s what the mocked function looks like for *Ellip*:

    func (_m *MockIndex) Ellip(_param0 string, _param1 ...interface{}) {
    	_s := []interface{}{_param0}
    	for _, _x := range _param1 {
    		_s = append(_s, _x)
    	}
    	_m.ctrl.Call(_m, &quot;Ellip&quot;, _s...)
    }
Notice anything odd? Well, gomock is creating a slice of interfaces, **_s**, initialized with the first parameter. Then it appends the variadic parameters to that slice of interfaces, **_s**.

So, to be clear, it doesn&#39;t just append the variadic parameter, **_param1**, to the slice. Each individual variadic from **_param1** is appended to the new slice, by iterating through it.

This means that the slice of variadic parameters is not preserved. It&#39;s broken out.


  [1]: https://github.com/rafrombrc/gomock/blob/9dcd4b2cd01be60f9fbabacce2a6ae1ed21ea48f/sample/user.go
  [2]: https://github.com/rafrombrc/gomock/blob/9dcd4b2cd01be60f9fbabacce2a6ae1ed21ea48f/sample/mock_user/mock_user.go

</details>



# 答案2
**得分**: 0

截至2017年10月1日`gomock.Any()`对于可变参数的工作是正确的https://github.com/golang/mock/pull/101

<details>
<summary>英文:</summary>

As of October 1, 2017, `gomock.Any()` works correctly for variadic args: https://github.com/golang/mock/pull/101

</details>



huangapple
  • 本文由 发表于 2016年2月25日 04:32:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/35612500.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定