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

问题描述 投票:0回答:3

我有一个

Printer
接口,使用标准 go
Printf
函数签名:

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

我希望能够使用 gomock 来模拟这个接口,但我不确定如何正确设置

tokens ...interface{}
参数。

我预计

Printf(gomock.Any(), gomock.Any())
将涵盖所有潜在情况(因为
tokens
编译为
[]interface{}
),但看来您需要设置对 N 个令牌的显式调用:

// 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

有谁知道更好的方法吗?

go mocking printf gomock
3个回答
2
投票

当前版本的 gomock 无法实现。也许您可以扩展它,并发送拉取请求。要了解为什么这是不可能的,您必须查看为可变参数函数生成的模拟。

为此,让我们看一下 gomock 存储库中的示例,特别是 ./sample/mock_user/user.go./sample/mock_user/mock_user.go

生成的模拟

您将在 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 中的每个单独的变量附加到新切片。

这意味着可变参数切片不会被保留。已经破了。


0
投票

自 2017 年 10 月 1 日起,

gomock.Any()
对于可变参数可以正常工作:https://github.com/golang/mock/pull/101


0
投票

一种方法是为可变参数定义一个自定义匹配器,用于检查提供的参数是否与预期的参数匹配。以下是如何执行此操作的示例:

// Custom matcher for variadic argument
type variadicMatcher struct {
    expected []interface{}
}

func (v variadicMatcher) Matches(x interface{}) bool {
    if len(v.expected) != len(x.([]interface{})) {
        return false
    }
    for i, val := range v.expected {
        if val != x.([]interface{})[i] {
            return false
        }
    }
    return true
    }



func (v variadicMatcher) String() string {
    return fmt.Sprintf("%v", v.expected)
}

// MatchesVariadic creates a variadicMatcher
func MatchesVariadic(expected ...interface{}) gomock.Matcher {
    return variadicMatcher{expected}
}


func TestPrinter(t *testing.T) {
    ctrl := gomock.NewController(t)
    defer ctrl.Finish()

    mockPrinter := NewMockPrinter(ctrl)

    // Setting up expectations with custom variadic matcher
    mockPrinter.EXPECT().
        Printf(gomock.Any(), MatchesVariadic("foo", 42)).
        AnyTimes()

    // Test with two variadic arguments
    mockPrinter.Printf("Test: %s, %d\n", "foo", 42)
}

我认为我们在进行单元测试时有限地使用了 gomock.Any() 。我希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.