如何向testify模拟的函数传递可变参数(ellipsis)?
问题:Testify Mock处理可变参数接口的调用错误
我在单元测试中使用testify,通过mockery生成了mock结构体。相关代码如下:
接口定义:
type Foo interface { Bar(...interface{}) }
mockery生成的mock结构体:
type Foo struct { mock.Mock } // Error provides a mock function with given fields: v func (_m *Foo) Bar(v ...interface{}) { var _ca []interface{} _ca = append(_ca, v...) _m.Called(_ca...) }
我尝试这样使用mock:
mockFoo := &mocks.Foo{} mockFoo.On("Bar", mock.Anything).Return()
但运行单元测试时出现错误:
Error(string,*errors.errorString) 0: "Error sending message" 1: &errors.errorString{s:"error"} The closest call I have is: Error(string) 0: "mock.Anything" Provided 1 arguments, mocked for 2 arguments Diff: 0: PASS: (string=Error sending message) == (string=mock.Anything) 1: FAIL: (*errors.errorString=error) != (Missing)
请问如何避免该错误,正确使用一个或多个参数调用On方法?
解决方法
错误原因
mockery生成的Bar方法会将传入的可变参数逐个展开后传给Called方法——也就是说实际调用Bar(a, b)时,Called会接收2个独立参数;而你设置的mock期望只匹配1个参数的调用,导致参数数量不匹配,触发报错。
具体写法
- 匹配固定数量的参数
如果明确实际调用会传入N个参数,直接在On方法中对应编写N个匹配器即可。比如实际调用传2个参数:
mockFoo := &mocks.Foo{} // 匹配任意两个参数的调用 mockFoo.On("Bar", mock.Anything, mock.Anything).Return() // 或者匹配特定值+任意类型参数 mockFoo.On("Bar", "Error sending message", mock.Anything).Return()
- 匹配任意数量的参数
如果需要兼容0个、1个或多个参数的调用场景,可以添加多个On期望,覆盖所有可能的参数数量:
mockFoo := &mocks.Foo{} // 匹配0个参数的调用 mockFoo.On("Bar").Return() // 匹配1个参数的调用 mockFoo.On("Bar", mock.Anything).Return() // 匹配2个参数的调用 mockFoo.On("Bar", mock.Anything, mock.Anything).Return() // 如需支持更多参数,继续添加对应期望即可
- 自定义匹配逻辑(可选)
如果不想逐个添加参数数量的期望,也可以使用mock.MatchedBy自定义匹配逻辑,比如匹配指定类型的参数组合:
mockFoo.On("Bar", mock.MatchedBy(func(v interface{}) bool { // 第一个参数需为string类型 _, ok := v.(string) return ok }), mock.MatchedBy(func(v interface{}) bool { // 第二个参数需为error类型 _, ok := v.(error) return ok })).Return()
内容的提问来源于stack exchange,提问作者akko
相关产品推荐
相关产品推荐

