From dc5539e60b321b00dd757e43ad04d97a2c55b7b3 Mon Sep 17 00:00:00 2001 From: Paul Cruickshank Date: Wed, 20 Apr 2022 19:26:47 +0100 Subject: [PATCH 1/5] Add support for generating mocks for generic interfaces --- go.mod | 28 ++++++- go.sum | 10 --- pkg/fixtures/generic.go | 21 +++++ pkg/generator.go | 75 +++++++++++++++--- pkg/generator_test.go | 164 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 275 insertions(+), 23 deletions(-) create mode 100644 pkg/fixtures/generic.go diff --git a/go.mod b/go.mod index de854205..de0d19a2 100644 --- a/go.mod +++ b/go.mod @@ -1,19 +1,39 @@ module github.com/vektra/mockery/v2 -go 1.16 +go 1.18 require ( github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.26.1 - github.com/spf13/afero v1.8.0 // indirect github.com/spf13/cobra v1.3.0 github.com/spf13/viper v1.10.1 github.com/stretchr/testify v1.7.0 golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce + golang.org/x/tools v0.1.10 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/magiconair/properties v1.8.5 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/pelletier/go-toml v1.9.4 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/spf13/afero v1.8.0 // indirect + github.com/spf13/cast v1.4.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.1.1 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/tools v0.1.10 + golang.org/x/text v0.3.7 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gopkg.in/ini.v1 v1.66.3 // indirect - gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index a57eaac4..fbdfb3ab 100644 --- a/go.sum +++ b/go.sum @@ -197,7 +197,6 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0 github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= -github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -317,7 +316,6 @@ github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= -github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -356,7 +354,6 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= @@ -382,7 +379,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI= @@ -468,8 +464,6 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -564,10 +558,8 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -681,7 +673,6 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -781,7 +772,6 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/pkg/fixtures/generic.go b/pkg/fixtures/generic.go new file mode 100644 index 00000000..f52cea9d --- /dev/null +++ b/pkg/fixtures/generic.go @@ -0,0 +1,21 @@ +package test + +type Constraint interface { + int +} + +type Generic[T Constraint] interface { + Get() T +} + +type GenericAny[T any] interface { + Get() T +} + +type GenericComparable[T comparable] interface { + Get() T +} + +type Embedded interface { + Generic[int] +} diff --git a/pkg/generator.go b/pkg/generator.go index a681e7df..0a19664a 100644 --- a/pkg/generator.go +++ b/pkg/generator.go @@ -71,6 +71,20 @@ func (g *Generator) populateImports(ctx context.Context) { log.Debug().Msgf("populating imports") + // imports from generic type constraints + if tParams := g.iface.NamedType.TypeParams(); tParams != nil && tParams.Len() > 0 { + for i := 0; i < tParams.Len(); i++ { + g.renderType(ctx, tParams.At(i).Constraint()) + } + } + + // imports from type arguments + if tArgs := g.iface.NamedType.TypeArgs(); tArgs != nil && tArgs.Len() > 0 { + for i := 0; i < tArgs.Len(); i++ { + g.renderType(ctx, tArgs.At(i)) + } + } + for _, method := range g.iface.Methods() { ftype := method.Signature g.addImportsFromTuple(ctx, ftype.Params()) @@ -88,6 +102,13 @@ func (g *Generator) addImportsFromTuple(ctx context.Context, list *types.Tuple) } } +func (g *Generator) addPackageScopedType(ctx context.Context, o *types.TypeName) string { + if o.Pkg() == nil || o.Pkg().Name() == "main" || (!g.KeepTree && g.InPackage && o.Pkg() == g.iface.Pkg) { + return o.Name() + } + return g.addPackageImport(ctx, o.Pkg()) + "." + o.Name() +} + func (g *Generator) addPackageImport(ctx context.Context, pkg *types.Package) string { return g.addPackageImportWithName(ctx, pkg.Path(), pkg.Name()) } @@ -231,6 +252,36 @@ func (g *Generator) mockName() string { return g.maybeMakeNameExported(g.iface.Name, g.Exported) } +func (g *Generator) typeConstraints(ctx context.Context) string { + tp := g.iface.NamedType.TypeParams() + if tp == nil || tp.Len() == 0 { + return "" + } + qualifiedParams := make([]string, 0, tp.Len()) + for i := 0; i < tp.Len(); i++ { + param := tp.At(i) + switch constraint := param.Constraint().(type) { + case *types.Named: + qualifiedParams = append(qualifiedParams, fmt.Sprintf("%s %s", param.String(), g.addPackageScopedType(ctx, constraint.Obj()))) + case *types.Interface: + qualifiedParams = append(qualifiedParams, fmt.Sprintf("%s %s", param.String(), constraint.String())) + } + } + return fmt.Sprintf("[%s]", strings.Join(qualifiedParams, ", ")) +} + +func (g *Generator) typeParams() string { + tp := g.iface.NamedType.TypeParams() + if tp == nil || tp.Len() == 0 { + return "" + } + params := make([]string, 0, tp.Len()) + for i := 0; i < tp.Len(); i++ { + params = append(params, tp.At(i).String()) + } + return fmt.Sprintf("[%s]", strings.Join(params, ", ")) +} + func (g *Generator) expecterName() string { return g.mockName() + "_Expecter" } @@ -335,11 +386,12 @@ type namer interface { func (g *Generator) renderType(ctx context.Context, typ types.Type) string { switch t := typ.(type) { case *types.Named: - o := t.Obj() - if o.Pkg() == nil || o.Pkg().Name() == "main" || (!g.KeepTree && g.InPackage && o.Pkg() == g.iface.Pkg) { - return o.Name() + return g.addPackageScopedType(ctx, t.Obj()) + case *types.TypeParam: + if t.Constraint() != nil { + return t.Obj().Name() } - return g.addPackageImport(ctx, o.Pkg()) + "." + o.Name() + return g.addPackageScopedType(ctx, t.Obj()) case *types.Basic: if t.Kind() == types.UnsafePointer { return "unsafe.Pointer" @@ -512,7 +564,7 @@ func (g *Generator) Generate(ctx context.Context) error { ) g.printf( - "type %s struct {\n\tmock.Mock\n}\n\n", g.mockName(), + "type %s%s struct {\n\tmock.Mock\n}\n\n", g.mockName(), g.typeConstraints(ctx), ) if g.WithExpecter { @@ -541,7 +593,7 @@ func (g *Generator) Generate(ctx context.Context) error { ) } g.printf( - "func (_m *%s) %s(%s) ", g.mockName(), fname, + "func (_m *%s%s) %s(%s) ", g.mockName(), g.typeParams(), fname, strings.Join(params.Params, ", "), ) @@ -612,7 +664,7 @@ func (g *Generator) Generate(ctx context.Context) error { } } - g.generateConstructor() + g.generateConstructor(ctx) return nil } @@ -712,7 +764,7 @@ func (_c *{{.CallStruct}}) Return({{range .Returns.Params}}{{.}},{{end}}) *{{.Ca `) } -func (g *Generator) generateConstructor() { +func (g *Generator) generateConstructor(ctx context.Context) { const constructorTemplate = ` type {{ .ConstructorTestingInterfaceName }} interface { mock.TestingT @@ -720,8 +772,9 @@ type {{ .ConstructorTestingInterfaceName }} interface { } // {{ .ConstructorName }} creates a new instance of {{ .MockName }}. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func {{ .ConstructorName }}(t {{ .ConstructorTestingInterfaceName }}) *{{ .MockName }} { +func {{ .ConstructorName }}{{ .TypeConstraint }}(t {{ .ConstructorTestingInterfaceName }}) *{{ .MockName }}{{ .TypeParams }} { mock := &{{ .MockName }}{} + mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) @@ -736,10 +789,14 @@ func {{ .ConstructorName }}(t {{ .ConstructorTestingInterfaceName }}) *{{ .MockN ConstructorName string ConstructorTestingInterfaceName string MockName string + TypeConstraint string + TypeParams string }{ ConstructorName: constructorName, ConstructorTestingInterfaceName: constructorName + "T", MockName: mockName, + TypeConstraint: g.typeConstraints(ctx), + TypeParams: g.typeParams(), } g.printTemplate(data, constructorTemplate) } diff --git a/pkg/generator_test.go b/pkg/generator_test.go index b47addef..fd846644 100644 --- a/pkg/generator_test.go +++ b/pkg/generator_test.go @@ -66,6 +66,10 @@ func (s *GeneratorSuite) checkGenerationWithConfig( return generator } + str := generator.buf.String() + if len(str) == 0 { + panic(str) + } // Mirror the formatting done by normally done by golang.org/x/tools/imports in Generator.Write. // // While we could possibly reuse Generator.Write here in addition to Generator.Generate, @@ -125,6 +129,166 @@ func (s *GeneratorSuite) TestCalculateImport() { s.Equal("d/src/c", calculateImport(ctx, gp, "d/src/c")) } +func (s *GeneratorSuite) TestGenericGenerator() { + expected := `// Generic is an autogenerated mock type for the Generic type +type Generic[T test.Constraint] struct { + mock.Mock +} + +// Get provides a mock function with given fields: +func (_m *Generic[T]) Get() T { + ret := _m.Called() + + var r0 T + if rf, ok := ret.Get(0).(func() T); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(T) + } + + return r0 +} + +// NewGeneric creates a new instance of Generic. It also registers a cleanup function to assert the mocks expectations. +func NewGeneric[T test.Constraint](t testing.TB) *Generic[T] { + mock := &Generic[T]{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} +` + s.checkGeneration("generic.go", "Generic", false, "", expected) +} + +func (s *GeneratorSuite) TestGenericInPkgGenerator() { + expected := `// MockGeneric is an autogenerated mock type for the Generic type +type MockGeneric[T Constraint] struct { + mock.Mock +} + +// Get provides a mock function with given fields: +func (_m *MockGeneric[T]) Get() T { + ret := _m.Called() + + var r0 T + if rf, ok := ret.Get(0).(func() T); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(T) + } + + return r0 +} + +// NewMockGeneric creates a new instance of MockGeneric. It also registers a cleanup function to assert the mocks expectations. +func NewMockGeneric[T Constraint](t testing.TB) *MockGeneric[T] { + mock := &MockGeneric[T]{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} +` + s.checkGeneration("generic.go", "Generic", true, "", expected) +} + +func (s *GeneratorSuite) TestGenericAnyGenerator() { + expected := `// GenericAny is an autogenerated mock type for the GenericAny type +type GenericAny[T any] struct { + mock.Mock +} + +// Get provides a mock function with given fields: +func (_m *GenericAny[T]) Get() T { + ret := _m.Called() + + var r0 T + if rf, ok := ret.Get(0).(func() T); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(T) + } + + return r0 +} + +// NewGenericAny creates a new instance of GenericAny. It also registers a cleanup function to assert the mocks expectations. +func NewGenericAny[T any](t testing.TB) *GenericAny[T] { + mock := &GenericAny[T]{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} +` + s.checkGeneration("generic.go", "GenericAny", false, "", expected) +} + +func (s *GeneratorSuite) TestGenericComparableGenerator() { + expected := `// GenericComparable is an autogenerated mock type for the GenericComparable type +type GenericComparable[T comparable] struct { + mock.Mock +} + +// Get provides a mock function with given fields: +func (_m *GenericComparable[T]) Get() T { + ret := _m.Called() + + var r0 T + if rf, ok := ret.Get(0).(func() T); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(T) + } + + return r0 +} + +// NewGenericComparable creates a new instance of GenericComparable. It also registers a cleanup function to assert the mocks expectations. +func NewGenericComparable[T comparable](t testing.TB) *GenericComparable[T] { + mock := &GenericComparable[T]{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} +` + s.checkGeneration("generic.go", "GenericComparable", false, "", expected) +} + +func (s *GeneratorSuite) TestEmbeddedGenericGenerator() { + expected := `// Embedded is an autogenerated mock type for the Embedded type +type Embedded struct { + mock.Mock +} + +// Get provides a mock function with given fields: +func (_m *Embedded) Get() int { + ret := _m.Called() + + var r0 int + if rf, ok := ret.Get(0).(func() int); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int) + } + + return r0 +} + +// NewEmbedded creates a new instance of Embedded. It also registers a cleanup function to assert the mocks expectations. +func NewEmbedded(t testing.TB) *Embedded { + mock := &Embedded{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} +` + s.checkGeneration("generic.go", "Embedded", false, "", expected) +} + func (s *GeneratorSuite) TestGenerator() { expected := `// Requester is an autogenerated mock type for the Requester type type Requester struct { From 33c4bf34b943bf4bdf3af90af233be91d9afd9df Mon Sep 17 00:00:00 2001 From: Paul Cruickshank Date: Fri, 22 Apr 2022 15:59:54 +0100 Subject: [PATCH 2/5] Generics mocking fixes - Add support for rendering union types - Add support for rendering the type arguments of named types - Add support for rendering types embedded in interfaces - Test generic generation against a single more complicated interface - Fix package namespacing on type arguments --- pkg/fixtures/constraints/constraints.go | 9 + pkg/fixtures/generic.go | 43 +++- pkg/generator.go | 42 ++- pkg/generator_test.go | 326 ++++++++++++------------ 4 files changed, 234 insertions(+), 186 deletions(-) create mode 100644 pkg/fixtures/constraints/constraints.go diff --git a/pkg/fixtures/constraints/constraints.go b/pkg/fixtures/constraints/constraints.go new file mode 100644 index 00000000..a17dc2e0 --- /dev/null +++ b/pkg/fixtures/constraints/constraints.go @@ -0,0 +1,9 @@ +package constraints + +type Signed interface { + ~int +} + +type Integer interface { + ~int +} diff --git a/pkg/fixtures/generic.go b/pkg/fixtures/generic.go index f52cea9d..802becb5 100644 --- a/pkg/fixtures/generic.go +++ b/pkg/fixtures/generic.go @@ -1,21 +1,38 @@ package test -type Constraint interface { - int -} +import ( + "io" -type Generic[T Constraint] interface { - Get() T -} + "github.com/vektra/mockery/v2/pkg/fixtures/constraints" +) -type GenericAny[T any] interface { - Get() T +type RequesterGenerics[ + TAny any, + TComparable comparable, + TSigned constraints.Signed, // external constraint + TIntf GetInt, // internal interface + TExternalIntf io.Writer, // external interface + TGenIntf GetGeneric[TSigned], // generic interface + TInlineType interface{ ~int | ~uint }, // inlined interface constraints + TInlineTypeGeneric interface { + ~int | GenericType[int, GetInt] + comparable + }, // inlined type constraints +] interface { + GenericArguments(TAny, TComparable) (TSigned, TIntf) + GenericStructs(GenericType[TAny, TIntf]) GenericType[TSigned, TIntf] + GenericAnonymousStructs(struct{ Type1 TExternalIntf }) struct { + Type2 GenericType[string, EmbeddedGet[int]] + } } -type GenericComparable[T comparable] interface { - Get() T +type GenericType[T any, S GetInt] struct { + Any T + Some []S } -type Embedded interface { - Generic[int] -} +type GetInt interface{ Get() int } + +type GetGeneric[T constraints.Integer] interface{ Get() T } + +type EmbeddedGet[T constraints.Signed] interface{ GetGeneric[T] } diff --git a/pkg/generator.go b/pkg/generator.go index 0a19664a..d4b3ff8d 100644 --- a/pkg/generator.go +++ b/pkg/generator.go @@ -260,12 +260,7 @@ func (g *Generator) typeConstraints(ctx context.Context) string { qualifiedParams := make([]string, 0, tp.Len()) for i := 0; i < tp.Len(); i++ { param := tp.At(i) - switch constraint := param.Constraint().(type) { - case *types.Named: - qualifiedParams = append(qualifiedParams, fmt.Sprintf("%s %s", param.String(), g.addPackageScopedType(ctx, constraint.Obj()))) - case *types.Interface: - qualifiedParams = append(qualifiedParams, fmt.Sprintf("%s %s", param.String(), constraint.String())) - } + qualifiedParams = append(qualifiedParams, fmt.Sprintf("%s %s", param.String(), g.renderType(ctx, param.Constraint()))) } return fmt.Sprintf("[%s]", strings.Join(qualifiedParams, ", ")) } @@ -386,7 +381,16 @@ type namer interface { func (g *Generator) renderType(ctx context.Context, typ types.Type) string { switch t := typ.(type) { case *types.Named: - return g.addPackageScopedType(ctx, t.Obj()) + name := g.addPackageScopedType(ctx, t.Obj()) + if t.TypeArgs() == nil || t.TypeArgs().Len() == 0 { + return name + } + args := make([]string, 0, t.TypeArgs().Len()) + for i := 0; i < t.TypeArgs().Len(); i++ { + arg := t.TypeArgs().At(i) + args = append(args, g.renderType(ctx, arg)) + } + return fmt.Sprintf("%s[%s]", name, strings.Join(args, ",")) case *types.TypeParam: if t.Constraint() != nil { return t.Obj().Name() @@ -456,7 +460,27 @@ func (g *Generator) renderType(ctx context.Context, typ types.Type) string { panic("Unable to mock inline interfaces with methods") } - return "interface{}" + rv := []string{"interface{"} + for i := 0; i < t.NumEmbeddeds(); i++ { + rv = append(rv, g.renderType(ctx, t.EmbeddedType(i))) + } + rv = append(rv, "}") + sep := "" + if t.NumEmbeddeds() > 1 { + sep = "\n" + } + return strings.Join(rv, sep) + case *types.Union: + rv := make([]string, 0, t.Len()) + for i := 0; i < t.Len(); i++ { + term := t.Term(i) + if term.Tilde() { + rv = append(rv, "~"+g.renderType(ctx, term.Type())) + } else { + rv = append(rv, g.renderType(ctx, term.Type())) + } + } + return strings.Join(rv, "|") case namer: return t.Name() default: @@ -593,7 +617,7 @@ func (g *Generator) Generate(ctx context.Context) error { ) } g.printf( - "func (_m *%s%s) %s(%s) ", g.mockName(), g.typeParams(), fname, + "func (_m *%s%s) %s(%s) ", g.mockName(), g.typeParams(ctx), fname, strings.Join(params.Params, ", "), ) diff --git a/pkg/generator_test.go b/pkg/generator_test.go index fd846644..199eb0a2 100644 --- a/pkg/generator_test.go +++ b/pkg/generator_test.go @@ -66,10 +66,6 @@ func (s *GeneratorSuite) checkGenerationWithConfig( return generator } - str := generator.buf.String() - if len(str) == 0 { - panic(str) - } // Mirror the formatting done by normally done by golang.org/x/tools/imports in Generator.Write. // // While we could possibly reuse Generator.Write here in addition to Generator.Generate, @@ -129,166 +125,6 @@ func (s *GeneratorSuite) TestCalculateImport() { s.Equal("d/src/c", calculateImport(ctx, gp, "d/src/c")) } -func (s *GeneratorSuite) TestGenericGenerator() { - expected := `// Generic is an autogenerated mock type for the Generic type -type Generic[T test.Constraint] struct { - mock.Mock -} - -// Get provides a mock function with given fields: -func (_m *Generic[T]) Get() T { - ret := _m.Called() - - var r0 T - if rf, ok := ret.Get(0).(func() T); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(T) - } - - return r0 -} - -// NewGeneric creates a new instance of Generic. It also registers a cleanup function to assert the mocks expectations. -func NewGeneric[T test.Constraint](t testing.TB) *Generic[T] { - mock := &Generic[T]{} - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} -` - s.checkGeneration("generic.go", "Generic", false, "", expected) -} - -func (s *GeneratorSuite) TestGenericInPkgGenerator() { - expected := `// MockGeneric is an autogenerated mock type for the Generic type -type MockGeneric[T Constraint] struct { - mock.Mock -} - -// Get provides a mock function with given fields: -func (_m *MockGeneric[T]) Get() T { - ret := _m.Called() - - var r0 T - if rf, ok := ret.Get(0).(func() T); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(T) - } - - return r0 -} - -// NewMockGeneric creates a new instance of MockGeneric. It also registers a cleanup function to assert the mocks expectations. -func NewMockGeneric[T Constraint](t testing.TB) *MockGeneric[T] { - mock := &MockGeneric[T]{} - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} -` - s.checkGeneration("generic.go", "Generic", true, "", expected) -} - -func (s *GeneratorSuite) TestGenericAnyGenerator() { - expected := `// GenericAny is an autogenerated mock type for the GenericAny type -type GenericAny[T any] struct { - mock.Mock -} - -// Get provides a mock function with given fields: -func (_m *GenericAny[T]) Get() T { - ret := _m.Called() - - var r0 T - if rf, ok := ret.Get(0).(func() T); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(T) - } - - return r0 -} - -// NewGenericAny creates a new instance of GenericAny. It also registers a cleanup function to assert the mocks expectations. -func NewGenericAny[T any](t testing.TB) *GenericAny[T] { - mock := &GenericAny[T]{} - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} -` - s.checkGeneration("generic.go", "GenericAny", false, "", expected) -} - -func (s *GeneratorSuite) TestGenericComparableGenerator() { - expected := `// GenericComparable is an autogenerated mock type for the GenericComparable type -type GenericComparable[T comparable] struct { - mock.Mock -} - -// Get provides a mock function with given fields: -func (_m *GenericComparable[T]) Get() T { - ret := _m.Called() - - var r0 T - if rf, ok := ret.Get(0).(func() T); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(T) - } - - return r0 -} - -// NewGenericComparable creates a new instance of GenericComparable. It also registers a cleanup function to assert the mocks expectations. -func NewGenericComparable[T comparable](t testing.TB) *GenericComparable[T] { - mock := &GenericComparable[T]{} - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} -` - s.checkGeneration("generic.go", "GenericComparable", false, "", expected) -} - -func (s *GeneratorSuite) TestEmbeddedGenericGenerator() { - expected := `// Embedded is an autogenerated mock type for the Embedded type -type Embedded struct { - mock.Mock -} - -// Get provides a mock function with given fields: -func (_m *Embedded) Get() int { - ret := _m.Called() - - var r0 int - if rf, ok := ret.Get(0).(func() int); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int) - } - - return r0 -} - -// NewEmbedded creates a new instance of Embedded. It also registers a cleanup function to assert the mocks expectations. -func NewEmbedded(t testing.TB) *Embedded { - mock := &Embedded{} - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} -` - s.checkGeneration("generic.go", "Embedded", false, "", expected) -} - func (s *GeneratorSuite) TestGenerator() { expected := `// Requester is an autogenerated mock type for the Requester type type Requester struct { @@ -2189,6 +2025,168 @@ import mock "github.com/stretchr/testify/mock" s.checkPrologueGeneration(generator, expected) } +func (s *GeneratorSuite) TestGenericGenerator() { + expected := `// RequesterGenerics is an autogenerated mock type for the RequesterGenerics type +type RequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf test.GetInt, TExternalIntf io.Writer, TGenIntf test.GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { + ~int | test.GenericType[int, test.GetInt] + comparable +}] struct { + mock.Mock +} + +// GenericAnonymousStructs provides a mock function with given fields: _a0 +func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericAnonymousStructs(_a0 struct{ Type1 TExternalIntf }) struct { + Type2 test.GenericType[string, test.EmbeddedGet[int]] +} { + ret := _m.Called(_a0) + + var r0 struct { + Type2 test.GenericType[string, test.EmbeddedGet[int]] + } + if rf, ok := ret.Get(0).(func(struct{ Type1 TExternalIntf }) struct { + Type2 test.GenericType[string, test.EmbeddedGet[int]] + }); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(struct { + Type2 test.GenericType[string, test.EmbeddedGet[int]] + }) + } + + return r0 +} + +// GenericArguments provides a mock function with given fields: _a0, _a1 +func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericArguments(_a0 TAny, _a1 TComparable) (TSigned, TIntf) { + ret := _m.Called(_a0, _a1) + + var r0 TSigned + if rf, ok := ret.Get(0).(func(TAny, TComparable) TSigned); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(TSigned) + } + + var r1 TIntf + if rf, ok := ret.Get(1).(func(TAny, TComparable) TIntf); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Get(1).(TIntf) + } + + return r0, r1 +} + +// GenericStructs provides a mock function with given fields: _a0 +func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericStructs(_a0 test.GenericType[TAny, TIntf]) test.GenericType[TSigned, TIntf] { + ret := _m.Called(_a0) + + var r0 test.GenericType[TSigned, TIntf] + if rf, ok := ret.Get(0).(func(test.GenericType[TAny, TIntf]) test.GenericType[TSigned, TIntf]); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(test.GenericType[TSigned, TIntf]) + } + + return r0 +} + +// NewRequesterGenerics creates a new instance of RequesterGenerics. It also registers a cleanup function to assert the mocks expectations. +func NewRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf test.GetInt, TExternalIntf io.Writer, TGenIntf test.GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { + ~int | test.GenericType[int, test.GetInt] + comparable +}](t testing.TB) *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { + mock := &RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} +` + s.checkGeneration("generic.go", "RequesterGenerics", false, "", expected) +} + +func (s *GeneratorSuite) TestGenericInpkgGenerator() { + expected := `// MockRequesterGenerics is an autogenerated mock type for the RequesterGenerics type +type MockRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf GetInt, TExternalIntf io.Writer, TGenIntf GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { + ~int | GenericType[int, GetInt] + comparable +}] struct { + mock.Mock +} + +// GenericAnonymousStructs provides a mock function with given fields: _a0 +func (_m *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericAnonymousStructs(_a0 struct{ Type1 TExternalIntf }) struct { + Type2 GenericType[string, EmbeddedGet[int]] +} { + ret := _m.Called(_a0) + + var r0 struct { + Type2 GenericType[string, EmbeddedGet[int]] + } + if rf, ok := ret.Get(0).(func(struct{ Type1 TExternalIntf }) struct { + Type2 GenericType[string, EmbeddedGet[int]] + }); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(struct { + Type2 GenericType[string, EmbeddedGet[int]] + }) + } + + return r0 +} + +// GenericArguments provides a mock function with given fields: _a0, _a1 +func (_m *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericArguments(_a0 TAny, _a1 TComparable) (TSigned, TIntf) { + ret := _m.Called(_a0, _a1) + + var r0 TSigned + if rf, ok := ret.Get(0).(func(TAny, TComparable) TSigned); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(TSigned) + } + + var r1 TIntf + if rf, ok := ret.Get(1).(func(TAny, TComparable) TIntf); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Get(1).(TIntf) + } + + return r0, r1 +} + +// GenericStructs provides a mock function with given fields: _a0 +func (_m *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericStructs(_a0 GenericType[TAny, TIntf]) GenericType[TSigned, TIntf] { + ret := _m.Called(_a0) + + var r0 GenericType[TSigned, TIntf] + if rf, ok := ret.Get(0).(func(GenericType[TAny, TIntf]) GenericType[TSigned, TIntf]); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(GenericType[TSigned, TIntf]) + } + + return r0 +} + +// NewMockRequesterGenerics creates a new instance of MockRequesterGenerics. It also registers a cleanup function to assert the mocks expectations. +func NewMockRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf GetInt, TExternalIntf io.Writer, TGenIntf GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { + ~int | GenericType[int, GetInt] + comparable +}](t testing.TB) *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { + mock := &MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} +` + s.checkGeneration("generic.go", "RequesterGenerics", true, "", expected) +} + func TestGeneratorSuite(t *testing.T) { generatorSuite := new(GeneratorSuite) suite.Run(t, generatorSuite) From a727d704867b17dc9e47e2351a675a81c5b584be Mon Sep 17 00:00:00 2001 From: Paul Cruickshank Date: Mon, 25 Apr 2022 09:27:48 +0100 Subject: [PATCH 3/5] Genrics support: rename and comment methods --- pkg/generator.go | 39 +++++++++++++++++++++++++++++---------- pkg/generator_test.go | 6 ++++-- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/pkg/generator.go b/pkg/generator.go index d4b3ff8d..5151f9ad 100644 --- a/pkg/generator.go +++ b/pkg/generator.go @@ -102,7 +102,12 @@ func (g *Generator) addImportsFromTuple(ctx context.Context, list *types.Tuple) } } -func (g *Generator) addPackageScopedType(ctx context.Context, o *types.TypeName) string { +// getPackageScopedType returns the appropriate string representation for the +// object TypeName. The string may either be the unqualified name (in the case +// the mock will live in the same package as the interface being mocked, e.g. +// `Foo`) or the package pathname (in the case the type lives in a package +// external to the mock, e.g. `packagename.Foo`). +func (g *Generator) getPackageScopedType(ctx context.Context, o *types.TypeName) string { if o.Pkg() == nil || o.Pkg().Name() == "main" || (!g.KeepTree && g.InPackage && o.Pkg() == g.iface.Pkg) { return o.Name() } @@ -252,7 +257,17 @@ func (g *Generator) mockName() string { return g.maybeMakeNameExported(g.iface.Name, g.Exported) } -func (g *Generator) typeConstraints(ctx context.Context) string { +// getTypeConstraintString returns type constraint string for a given interface. +// For instance, a method using this constraint: +// +// func Foo[T Stringer](s []T) (ret []string) { +// +// } +// +// The constraint returned will be "[T Stringer]" +// +// https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#type-parameters +func (g *Generator) getTypeConstraintString(ctx context.Context) string { tp := g.iface.NamedType.TypeParams() if tp == nil || tp.Len() == 0 { return "" @@ -265,7 +280,10 @@ func (g *Generator) typeConstraints(ctx context.Context) string { return fmt.Sprintf("[%s]", strings.Join(qualifiedParams, ", ")) } -func (g *Generator) typeParams() string { +// getInstantiatedTypeString returns the "instantiated" type names for a given +// constraint list. For instance, if your interface has the constraints +// `[S Stringer, I int, C Comparable]`, this method would return: `[S, I, C]` +func (g *Generator) getInstantiatedTypeString() string { tp := g.iface.NamedType.TypeParams() if tp == nil || tp.Len() == 0 { return "" @@ -381,7 +399,7 @@ type namer interface { func (g *Generator) renderType(ctx context.Context, typ types.Type) string { switch t := typ.(type) { case *types.Named: - name := g.addPackageScopedType(ctx, t.Obj()) + name := g.getPackageScopedType(ctx, t.Obj()) if t.TypeArgs() == nil || t.TypeArgs().Len() == 0 { return name } @@ -395,7 +413,7 @@ func (g *Generator) renderType(ctx context.Context, typ types.Type) string { if t.Constraint() != nil { return t.Obj().Name() } - return g.addPackageScopedType(ctx, t.Obj()) + return g.getPackageScopedType(ctx, t.Obj()) case *types.Basic: if t.Kind() == types.UnsafePointer { return "unsafe.Pointer" @@ -588,7 +606,7 @@ func (g *Generator) Generate(ctx context.Context) error { ) g.printf( - "type %s%s struct {\n\tmock.Mock\n}\n\n", g.mockName(), g.typeConstraints(ctx), + "type %s%s struct {\n\tmock.Mock\n}\n\n", g.mockName(), g.getTypeConstraintString(ctx), ) if g.WithExpecter { @@ -617,7 +635,7 @@ func (g *Generator) Generate(ctx context.Context) error { ) } g.printf( - "func (_m *%s%s) %s(%s) ", g.mockName(), g.typeParams(ctx), fname, + "func (_m *%s%s) %s(%s) ", g.mockName(), g.getInstantiatedTypeString(), fname, strings.Join(params.Params, ", "), ) @@ -797,7 +815,7 @@ type {{ .ConstructorTestingInterfaceName }} interface { // {{ .ConstructorName }} creates a new instance of {{ .MockName }}. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. func {{ .ConstructorName }}{{ .TypeConstraint }}(t {{ .ConstructorTestingInterfaceName }}) *{{ .MockName }}{{ .TypeParams }} { - mock := &{{ .MockName }}{} + mock := &{{ .MockName }}{{ .InstantiatedTypeString }}{} mock.Mock.Test(t) @@ -812,15 +830,16 @@ func {{ .ConstructorName }}{{ .TypeConstraint }}(t {{ .ConstructorTestingInterfa data := struct { ConstructorName string ConstructorTestingInterfaceName string + InstantiatedTypeString string MockName string TypeConstraint string TypeParams string }{ ConstructorName: constructorName, ConstructorTestingInterfaceName: constructorName + "T", + InstantiatedTypeString: g.getInstantiatedTypeString(), MockName: mockName, - TypeConstraint: g.typeConstraints(ctx), - TypeParams: g.typeParams(), + TypeConstraint: g.getTypeConstraintString(ctx), } g.printTemplate(data, constructorTemplate) } diff --git a/pkg/generator_test.go b/pkg/generator_test.go index 199eb0a2..fa65822d 100644 --- a/pkg/generator_test.go +++ b/pkg/generator_test.go @@ -2091,12 +2091,13 @@ func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TG return r0 } -// NewRequesterGenerics creates a new instance of RequesterGenerics. It also registers a cleanup function to assert the mocks expectations. +// NewRequesterGenerics creates a new instance of RequesterGenerics. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. func NewRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf test.GetInt, TExternalIntf io.Writer, TGenIntf test.GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { ~int | test.GenericType[int, test.GetInt] comparable }](t testing.TB) *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { mock := &RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{} + mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) @@ -2172,12 +2173,13 @@ func (_m *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf return r0 } -// NewMockRequesterGenerics creates a new instance of MockRequesterGenerics. It also registers a cleanup function to assert the mocks expectations. +// NewMockRequesterGenerics creates a new instance of MockRequesterGenerics. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. func NewMockRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf GetInt, TExternalIntf io.Writer, TGenIntf GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { ~int | GenericType[int, GetInt] comparable }](t testing.TB) *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { mock := &MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{} + mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) From ed55a470b65db96e335846d7c22bea8235c93a89 Mon Sep 17 00:00:00 2001 From: Paul Cruickshank Date: Tue, 17 May 2022 12:22:01 +0100 Subject: [PATCH 4/5] Update x/tools to pick up fix for https://github.com/golang/go/issues/51629 --- go.mod | 5 ++--- go.sum | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index de0d19a2..3950b834 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/spf13/viper v1.10.1 github.com/stretchr/testify v1.7.0 golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce - golang.org/x/tools v0.1.10 + golang.org/x/tools v0.1.11-0.20220502222022-556c550a3816 gopkg.in/yaml.v2 v2.4.0 ) @@ -29,11 +29,10 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.1.1 // indirect github.com/subosito/gotenv v1.2.0 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gopkg.in/ini.v1 v1.66.3 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index fbdfb3ab..7a184db4 100644 --- a/go.sum +++ b/go.sum @@ -419,8 +419,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -634,12 +634,11 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.11-0.20220502222022-556c550a3816 h1:KDN1gdvkjXcpAMWJCUAIM1WiDgcWqr91B58SpqEAG4E= +golang.org/x/tools v0.1.11-0.20220502222022-556c550a3816/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= From 4c0f6c85e0e283559c6f9ed1b0620236635c3426 Mon Sep 17 00:00:00 2001 From: LandonTClipp Date: Tue, 24 May 2022 11:14:59 -0500 Subject: [PATCH 5/5] Merge conflict resolution Re-run mock generation Fix tests --- mocks/pkg/fixtures/EmbeddedGet.go | 42 ++++++++++ mocks/pkg/fixtures/GetGeneric.go | 42 ++++++++++ mocks/pkg/fixtures/GetInt.go | 39 +++++++++ mocks/pkg/fixtures/RequesterGenerics.go | 96 +++++++++++++++++++++++ mocks/pkg/fixtures/constraints/Integer.go | 25 ++++++ mocks/pkg/fixtures/constraints/Signed.go | 25 ++++++ pkg/generator.go | 4 +- pkg/generator_test.go | 18 ++++- 8 files changed, 284 insertions(+), 7 deletions(-) create mode 100644 mocks/pkg/fixtures/EmbeddedGet.go create mode 100644 mocks/pkg/fixtures/GetGeneric.go create mode 100644 mocks/pkg/fixtures/GetInt.go create mode 100644 mocks/pkg/fixtures/RequesterGenerics.go create mode 100644 mocks/pkg/fixtures/constraints/Integer.go create mode 100644 mocks/pkg/fixtures/constraints/Signed.go diff --git a/mocks/pkg/fixtures/EmbeddedGet.go b/mocks/pkg/fixtures/EmbeddedGet.go new file mode 100644 index 00000000..c91df07e --- /dev/null +++ b/mocks/pkg/fixtures/EmbeddedGet.go @@ -0,0 +1,42 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + constraints "github.com/vektra/mockery/v2/pkg/fixtures/constraints" +) + +// EmbeddedGet is an autogenerated mock type for the EmbeddedGet type +type EmbeddedGet[T constraints.Signed] struct { + mock.Mock +} + +// Get provides a mock function with given fields: +func (_m *EmbeddedGet[T]) Get() T { + ret := _m.Called() + + var r0 T + if rf, ok := ret.Get(0).(func() T); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(T) + } + + return r0 +} + +type NewEmbeddedGetT interface { + mock.TestingT + Cleanup(func()) +} + +// NewEmbeddedGet creates a new instance of EmbeddedGet. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewEmbeddedGet[T constraints.Signed](t NewEmbeddedGetT) *EmbeddedGet[T] { + mock := &EmbeddedGet[T]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/pkg/fixtures/GetGeneric.go b/mocks/pkg/fixtures/GetGeneric.go new file mode 100644 index 00000000..67d1f578 --- /dev/null +++ b/mocks/pkg/fixtures/GetGeneric.go @@ -0,0 +1,42 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + constraints "github.com/vektra/mockery/v2/pkg/fixtures/constraints" +) + +// GetGeneric is an autogenerated mock type for the GetGeneric type +type GetGeneric[T constraints.Integer] struct { + mock.Mock +} + +// Get provides a mock function with given fields: +func (_m *GetGeneric[T]) Get() T { + ret := _m.Called() + + var r0 T + if rf, ok := ret.Get(0).(func() T); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(T) + } + + return r0 +} + +type NewGetGenericT interface { + mock.TestingT + Cleanup(func()) +} + +// NewGetGeneric creates a new instance of GetGeneric. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewGetGeneric[T constraints.Integer](t NewGetGenericT) *GetGeneric[T] { + mock := &GetGeneric[T]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/pkg/fixtures/GetInt.go b/mocks/pkg/fixtures/GetInt.go new file mode 100644 index 00000000..8dfe94b5 --- /dev/null +++ b/mocks/pkg/fixtures/GetInt.go @@ -0,0 +1,39 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// GetInt is an autogenerated mock type for the GetInt type +type GetInt struct { + mock.Mock +} + +// Get provides a mock function with given fields: +func (_m *GetInt) Get() int { + ret := _m.Called() + + var r0 int + if rf, ok := ret.Get(0).(func() int); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int) + } + + return r0 +} + +type NewGetIntT interface { + mock.TestingT + Cleanup(func()) +} + +// NewGetInt creates a new instance of GetInt. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewGetInt(t NewGetIntT) *GetInt { + mock := &GetInt{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/pkg/fixtures/RequesterGenerics.go b/mocks/pkg/fixtures/RequesterGenerics.go new file mode 100644 index 00000000..433e1b63 --- /dev/null +++ b/mocks/pkg/fixtures/RequesterGenerics.go @@ -0,0 +1,96 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + io "io" + + constraints "github.com/vektra/mockery/v2/pkg/fixtures/constraints" + + mock "github.com/stretchr/testify/mock" + + test "github.com/vektra/mockery/v2/pkg/fixtures" +) + +// RequesterGenerics is an autogenerated mock type for the RequesterGenerics type +type RequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf test.GetInt, TExternalIntf io.Writer, TGenIntf test.GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { + ~int | test.GenericType[int, test.GetInt] + comparable +}] struct { + mock.Mock +} + +// GenericAnonymousStructs provides a mock function with given fields: _a0 +func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericAnonymousStructs(_a0 struct{ Type1 TExternalIntf }) struct { + Type2 test.GenericType[string, test.EmbeddedGet[int]] +} { + ret := _m.Called(_a0) + + var r0 struct { + Type2 test.GenericType[string, test.EmbeddedGet[int]] + } + if rf, ok := ret.Get(0).(func(struct{ Type1 TExternalIntf }) struct { + Type2 test.GenericType[string, test.EmbeddedGet[int]] + }); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(struct { + Type2 test.GenericType[string, test.EmbeddedGet[int]] + }) + } + + return r0 +} + +// GenericArguments provides a mock function with given fields: _a0, _a1 +func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericArguments(_a0 TAny, _a1 TComparable) (TSigned, TIntf) { + ret := _m.Called(_a0, _a1) + + var r0 TSigned + if rf, ok := ret.Get(0).(func(TAny, TComparable) TSigned); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(TSigned) + } + + var r1 TIntf + if rf, ok := ret.Get(1).(func(TAny, TComparable) TIntf); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Get(1).(TIntf) + } + + return r0, r1 +} + +// GenericStructs provides a mock function with given fields: _a0 +func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]) GenericStructs(_a0 test.GenericType[TAny, TIntf]) test.GenericType[TSigned, TIntf] { + ret := _m.Called(_a0) + + var r0 test.GenericType[TSigned, TIntf] + if rf, ok := ret.Get(0).(func(test.GenericType[TAny, TIntf]) test.GenericType[TSigned, TIntf]); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(test.GenericType[TSigned, TIntf]) + } + + return r0 +} + +type NewRequesterGenericsT interface { + mock.TestingT + Cleanup(func()) +} + +// NewRequesterGenerics creates a new instance of RequesterGenerics. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf test.GetInt, TExternalIntf io.Writer, TGenIntf test.GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { + ~int | test.GenericType[int, test.GetInt] + comparable +}](t NewRequesterGenericsT) *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { + mock := &RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/pkg/fixtures/constraints/Integer.go b/mocks/pkg/fixtures/constraints/Integer.go new file mode 100644 index 00000000..61b21e81 --- /dev/null +++ b/mocks/pkg/fixtures/constraints/Integer.go @@ -0,0 +1,25 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// Integer is an autogenerated mock type for the Integer type +type Integer struct { + mock.Mock +} + +type NewIntegerT interface { + mock.TestingT + Cleanup(func()) +} + +// NewInteger creates a new instance of Integer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewInteger(t NewIntegerT) *Integer { + mock := &Integer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/pkg/fixtures/constraints/Signed.go b/mocks/pkg/fixtures/constraints/Signed.go new file mode 100644 index 00000000..30b94696 --- /dev/null +++ b/mocks/pkg/fixtures/constraints/Signed.go @@ -0,0 +1,25 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// Signed is an autogenerated mock type for the Signed type +type Signed struct { + mock.Mock +} + +type NewSignedT interface { + mock.TestingT + Cleanup(func()) +} + +// NewSigned creates a new instance of Signed. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewSigned(t NewSignedT) *Signed { + mock := &Signed{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/generator.go b/pkg/generator.go index 5151f9ad..539dc17f 100644 --- a/pkg/generator.go +++ b/pkg/generator.go @@ -814,9 +814,8 @@ type {{ .ConstructorTestingInterfaceName }} interface { } // {{ .ConstructorName }} creates a new instance of {{ .MockName }}. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func {{ .ConstructorName }}{{ .TypeConstraint }}(t {{ .ConstructorTestingInterfaceName }}) *{{ .MockName }}{{ .TypeParams }} { +func {{ .ConstructorName }}{{ .TypeConstraint }}(t {{ .ConstructorTestingInterfaceName }}) *{{ .MockName }}{{ .InstantiatedTypeString }} { mock := &{{ .MockName }}{{ .InstantiatedTypeString }}{} - mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) @@ -833,7 +832,6 @@ func {{ .ConstructorName }}{{ .TypeConstraint }}(t {{ .ConstructorTestingInterfa InstantiatedTypeString string MockName string TypeConstraint string - TypeParams string }{ ConstructorName: constructorName, ConstructorTestingInterfaceName: constructorName + "T", diff --git a/pkg/generator_test.go b/pkg/generator_test.go index fa65822d..2d5190f0 100644 --- a/pkg/generator_test.go +++ b/pkg/generator_test.go @@ -2091,11 +2091,16 @@ func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TG return r0 } -// NewRequesterGenerics creates a new instance of RequesterGenerics. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +type NewRequesterGenericsT interface { + mock.TestingT + Cleanup(func()) +} + +// NewRequesterGenerics creates a new instance of RequesterGenerics. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. func NewRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf test.GetInt, TExternalIntf io.Writer, TGenIntf test.GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { ~int | test.GenericType[int, test.GetInt] comparable -}](t testing.TB) *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { +}](t NewRequesterGenericsT) *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { mock := &RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{} mock.Mock.Test(t) @@ -2173,11 +2178,16 @@ func (_m *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf return r0 } -// NewMockRequesterGenerics creates a new instance of MockRequesterGenerics. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +type NewMockRequesterGenericsT interface { + mock.TestingT + Cleanup(func()) +} + +// NewMockRequesterGenerics creates a new instance of MockRequesterGenerics. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. func NewMockRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf GetInt, TExternalIntf io.Writer, TGenIntf GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface { ~int | GenericType[int, GetInt] comparable -}](t testing.TB) *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { +}](t NewMockRequesterGenericsT) *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] { mock := &MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{} mock.Mock.Test(t)