diff --git a/.mockery.yaml b/.mockery.yaml index 2ae36ff0..2559bb86 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -36,11 +36,11 @@ packages: unroll-variadic: False - mockname: Expecter unroll-variadic: True + RequesterReturnElided: VariadicNoReturnInterface: config: with-expecter: True unroll-variadic: False - RequesterReturnElided: github.com/vektra/mockery/v2/pkg/fixtures/recursive_generation: config: recursive: True diff --git a/Taskfile.yml b/Taskfile.yml index f9686331..5e11bb39 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -13,12 +13,16 @@ tasks: - "**/*.go" cmds: - go fmt ./... - + + mocks: + desc: generate new mocks from scratch + deps: [mocks.remove, mocks.generate] + mocks.remove: desc: remove all mock files cmds: - - find . -name '*_mock.go' | xargs rm - - rm -rf mocks/ + - find . -name '*_mock.go' | xargs rm + - rm -rf mocks/ mocks.generate: desc: generate mockery mocks @@ -75,6 +79,5 @@ tasks: - task: test - task: test.e2e - default: deps: [test.ci] diff --git a/mocks/github.com/vektra/mockery/v2/pkg/fixtures/Variadic.go b/mocks/github.com/vektra/mockery/v2/pkg/fixtures/Variadic.go new file mode 100644 index 00000000..4ee76f41 --- /dev/null +++ b/mocks/github.com/vektra/mockery/v2/pkg/fixtures/Variadic.go @@ -0,0 +1,75 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// Variadic is an autogenerated mock type for the Variadic type +type Variadic struct { + mock.Mock +} + +type Variadic_Expecter struct { + mock *mock.Mock +} + +func (_m *Variadic) EXPECT() *Variadic_Expecter { + return &Variadic_Expecter{mock: &_m.Mock} +} + +// VariadicFunction provides a mock function with given fields: str, vFunc +func (_m *Variadic) VariadicFunction(str string, vFunc func(string, ...interface{}) interface{}) error { + ret := _m.Called(str, vFunc) + + var r0 error + if rf, ok := ret.Get(0).(func(string, func(string, ...interface{}) interface{}) error); ok { + r0 = rf(str, vFunc) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Variadic_VariadicFunction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'VariadicFunction' +type Variadic_VariadicFunction_Call struct { + *mock.Call +} + +// VariadicFunction is a helper method to define mock.On call +// - str string +// - vFunc func(string , ...interface{}) interface{} +func (_e *Variadic_Expecter) VariadicFunction(str interface{}, vFunc ...interface{}) *Variadic_VariadicFunction_Call { + return &Variadic_VariadicFunction_Call{Call: _e.mock.On("VariadicFunction", str, vFunc)} +} + +func (_c *Variadic_VariadicFunction_Call) Run(run func(str string, vFunc func(string, ...interface{}) interface{})) *Variadic_VariadicFunction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(func(string, ...interface{}) interface{})) + }) + return _c +} + +func (_c *Variadic_VariadicFunction_Call) Return(_a0 error) *Variadic_VariadicFunction_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Variadic_VariadicFunction_Call) RunAndReturn(run func(string, func(string, ...interface{}) interface{}) error) *Variadic_VariadicFunction_Call { + _c.Call.Return(run) + return _c +} + +// NewVariadic creates a new instance of Variadic. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewVariadic(t interface { + mock.TestingT + Cleanup(func()) +}) *Variadic { + mock := &Variadic{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/github.com/vektra/mockery/v2/pkg/fixtures/VariadicReturnFunc.go b/mocks/github.com/vektra/mockery/v2/pkg/fixtures/VariadicReturnFunc.go new file mode 100644 index 00000000..181b07d9 --- /dev/null +++ b/mocks/github.com/vektra/mockery/v2/pkg/fixtures/VariadicReturnFunc.go @@ -0,0 +1,76 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// VariadicReturnFunc is an autogenerated mock type for the VariadicReturnFunc type +type VariadicReturnFunc struct { + mock.Mock +} + +type VariadicReturnFunc_Expecter struct { + mock *mock.Mock +} + +func (_m *VariadicReturnFunc) EXPECT() *VariadicReturnFunc_Expecter { + return &VariadicReturnFunc_Expecter{mock: &_m.Mock} +} + +// SampleMethod provides a mock function with given fields: str +func (_m *VariadicReturnFunc) SampleMethod(str string) func(string, []int, ...interface{}) { + ret := _m.Called(str) + + var r0 func(string, []int, ...interface{}) + if rf, ok := ret.Get(0).(func(string) func(string, []int, ...interface{})); ok { + r0 = rf(str) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(func(string, []int, ...interface{})) + } + } + + return r0 +} + +// VariadicReturnFunc_SampleMethod_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SampleMethod' +type VariadicReturnFunc_SampleMethod_Call struct { + *mock.Call +} + +// SampleMethod is a helper method to define mock.On call +// - str string +func (_e *VariadicReturnFunc_Expecter) SampleMethod(str interface{}) *VariadicReturnFunc_SampleMethod_Call { + return &VariadicReturnFunc_SampleMethod_Call{Call: _e.mock.On("SampleMethod", str)} +} + +func (_c *VariadicReturnFunc_SampleMethod_Call) Run(run func(str string)) *VariadicReturnFunc_SampleMethod_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *VariadicReturnFunc_SampleMethod_Call) Return(_a0 func(string, []int, ...interface{})) *VariadicReturnFunc_SampleMethod_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *VariadicReturnFunc_SampleMethod_Call) RunAndReturn(run func(string) func(string, []int, ...interface{})) *VariadicReturnFunc_SampleMethod_Call { + _c.Call.Return(run) + return _c +} + +// NewVariadicReturnFunc creates a new instance of VariadicReturnFunc. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewVariadicReturnFunc(t interface { + mock.TestingT + Cleanup(func()) +}) *VariadicReturnFunc { + mock := &VariadicReturnFunc{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/fixtures/test/variadic_return_func_test.go b/pkg/fixtures/test/variadic_return_func_test.go new file mode 100644 index 00000000..6fb3a8ba --- /dev/null +++ b/pkg/fixtures/test/variadic_return_func_test.go @@ -0,0 +1,18 @@ +package test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + mocks "github.com/vektra/mockery/v2/mocks/github.com/vektra/mockery/v2/pkg/fixtures" +) + +func TestVariadicReturnFunc(t *testing.T) { + m := mocks.NewVariadicReturnFunc(t) + m.EXPECT().SampleMethod("").Return(func(s string, l []int, a ...any) { + assert.Equal(t, "foo", s) + assert.Equal(t, []int{1, 2, 3}, l) + assert.Equal(t, []any{"one", "two", "three"}, a) + }) + m.SampleMethod("")("foo", []int{1, 2, 3}, "one", "two", "three") +} diff --git a/pkg/fixtures/variadic.go b/pkg/fixtures/variadic.go new file mode 100644 index 00000000..3e08465b --- /dev/null +++ b/pkg/fixtures/variadic.go @@ -0,0 +1,8 @@ +package test + +type VariadicFunction = func(args1 string, args2 ...interface{}) interface{} + +type Variadic interface { + VariadicFunction(str string, vFunc VariadicFunction) error +} + diff --git a/pkg/fixtures/variadic_return_func.go b/pkg/fixtures/variadic_return_func.go new file mode 100644 index 00000000..720e05cc --- /dev/null +++ b/pkg/fixtures/variadic_return_func.go @@ -0,0 +1,5 @@ +package test + +type VariadicReturnFunc interface { + SampleMethod(str string) func(str string, arr []int, a ...interface{}) +} diff --git a/pkg/generator.go b/pkg/generator.go index 6a9d9034..85ce89ee 100644 --- a/pkg/generator.go +++ b/pkg/generator.go @@ -494,19 +494,19 @@ func (g *Generator) renderType(ctx context.Context, typ types.Type) string { case 0: return fmt.Sprintf( "func(%s)", - g.renderTypeTuple(ctx, t.Params()), + g.renderTypeTuple(ctx, t.Params(), t.Variadic()), ) case 1: return fmt.Sprintf( "func(%s) %s", - g.renderTypeTuple(ctx, t.Params()), + g.renderTypeTuple(ctx, t.Params(), t.Variadic()), g.renderType(ctx, t.Results().At(0).Type()), ) default: return fmt.Sprintf( "func(%s)(%s)", - g.renderTypeTuple(ctx, t.Params()), - g.renderTypeTuple(ctx, t.Results()), + g.renderTypeTuple(ctx, t.Params(), t.Variadic()), + g.renderTypeTuple(ctx, t.Results(), t.Variadic()), ) } case *types.Map: @@ -575,13 +575,20 @@ func (g *Generator) renderType(ctx context.Context, typ types.Type) string { } } -func (g *Generator) renderTypeTuple(ctx context.Context, tup *types.Tuple) string { +func (g *Generator) renderTypeTuple(ctx context.Context, tup *types.Tuple, variadic bool) string { var parts []string for i := 0; i < tup.Len(); i++ { v := tup.At(i) - parts = append(parts, g.renderType(ctx, v.Type())) + if variadic && i == tup.Len()-1 { + t := v.Type() + elem := t.(*types.Slice).Elem() + + parts = append(parts, "..."+g.renderType(ctx, elem)) + } else { + parts = append(parts, g.renderType(ctx, v.Type())) + } } return strings.Join(parts, " , ")