diff --git a/.mockery.yaml b/.mockery.yaml index ed90f364..c5a68623 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -5,6 +5,7 @@ mockname: "{{.InterfaceName}}" filename: "{{.MockName}}.go" outpkg: mocks tags: "custom2" +issue-845-fix: True packages: github.com/vektra/mockery/v2/pkg/fixtures/buildtag/comment: config: @@ -78,3 +79,18 @@ packages: outpkg: "{{.PackageName}}_test" filename: "{{.InterfaceNameSnake}}_mock_test.go" keeptree: True + github.com/vektra/mockery/v2/pkg/fixtures/issue845: + config: + all: True + dir: "{{.InterfaceDir}}" + mockname: "{{.InterfaceName}}" + outpkg: "{{.PackageName}}_test" + filename: "mock_{{.MockName}}_test.go" + inpackage: True + interfaces: + Interface: + configs: + - issue-845-fix: False + mockname: WithoutFix + - issue-845-fix: True + mockname: WithFix diff --git a/cmd/mockery.go b/cmd/mockery.go index fc24680a..ac0b7737 100644 --- a/cmd/mockery.go +++ b/cmd/mockery.go @@ -12,7 +12,6 @@ import ( "github.com/chigopher/pathlib" "github.com/mitchellh/go-homedir" - "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -297,7 +296,7 @@ func (r *RootApp) Run() error { log.Fatal().Msgf("Use --name to specify the name of the interface or --all for all interfaces found") } - warnDeprecated( + logging.WarnDeprecated( ctx, "use of the packages config will be the only way to generate mocks in v3. Please migrate your config to use the packages feature.", map[string]any{ @@ -389,25 +388,3 @@ func (r *RootApp) Run() error { return nil } - -func warn(ctx context.Context, prefix string, message string, fields map[string]any) { - log := zerolog.Ctx(ctx) - event := log.Warn() - if fields != nil { - event = event.Fields(fields) - } - event.Msgf("%s: %s", prefix, message) -} - -func info(ctx context.Context, prefix string, message string, fields map[string]any) { - log := zerolog.Ctx(ctx) - event := log.Info() - if fields != nil { - event = event.Fields(fields) - } - event.Msgf("%s: %s", prefix, message) -} - -func warnDeprecated(ctx context.Context, message string, fields map[string]any) { - warn(ctx, "DEPRECATION", message, fields) -} diff --git a/docs/deprecations.md b/docs/deprecations.md new file mode 100644 index 00000000..6babcff6 --- /dev/null +++ b/docs/deprecations.md @@ -0,0 +1,38 @@ +Deprecations +============= + +`packages` +---------- + +The [`packages`](features.md#packages-configuration) feature will be the only way to configure mockery in the future. + +`issue-845-fix` +--------------- + +This parameter fixes a somewhat uninteresting, but important issue found in [#845](https://github.com/vektra/mockery/issues/845). +In short, mockery ignored the `#!yaml outpkg:` parameter if `#!yaml inpackage:` was set to `#!yaml True`. This prevents users +from being able to set alternate package names for their mocks that are generated in the same directory +as the mocked interface. For example, it's legal Go to append `_test` to the mock package name +if the file is appended with `_test.go` as well. This parameter will be permanently +enabled in mockery v3. + +As an example, if you had configuration that looked like this: + +```yaml +all: True +dir: "{{.InterfaceDir}}" +mockname: "{{.InterfaceName}}Mock" +outpkg: "{{.PackageName}}_test" +filename: "mock_{{.InterfaceName}}_test.go" +inpackage: True +``` + +The `#!yaml outpkg` parameter would not be respected and instead would be forced to take on the value of `#!yaml "{{.PackageName}}"`. +To remove the warning, you must set: + +```yaml +issue-845-fix: True +``` + +After this is done, mocks generated in the old scheme will properly respect the `#!yaml outpkg:` parameter previously set +if being generated with `#!yaml inpackage: True`. diff --git a/mkdocs.yml b/mkdocs.yml index 4959ac1d..e5f71212 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -67,6 +67,7 @@ nav: - FAQ: notes.md - Changelog: changelog.md - Migrating to Packages: migrating_to_packages.md + - Deprecations: deprecations.md extra_css: - stylesheets/extra.css diff --git a/pkg/config/config.go b/pkg/config/config.go index d3928e6a..7ff9d5ad 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -50,6 +50,7 @@ type Config struct { IncludeRegex string `mapstructure:"include-regex"` InPackage bool `mapstructure:"inpackage"` InPackageSuffix bool `mapstructure:"inpackage-suffix"` + Issue845Fix bool `mapstructure:"issue-845-fix"` KeepTree bool `mapstructure:"keeptree"` LogLevel string `mapstructure:"log-level"` MockName string `mapstructure:"mockname"` diff --git a/pkg/fixtures/issue845/interface.go b/pkg/fixtures/issue845/interface.go new file mode 100644 index 00000000..228bc1fa --- /dev/null +++ b/pkg/fixtures/issue845/interface.go @@ -0,0 +1,5 @@ +package issue845 + +type Interface interface { + Foo() string +} diff --git a/pkg/fixtures/issue845/interface_test.go b/pkg/fixtures/issue845/interface_test.go new file mode 100644 index 00000000..c62e5b3d --- /dev/null +++ b/pkg/fixtures/issue845/interface_test.go @@ -0,0 +1,40 @@ +package issue845 + +import ( + "strings" + "testing" + + "github.com/chigopher/pathlib" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFix(t *testing.T) { + for _, tt := range []struct { + name string + filepath string + expectedPackage string + }{ + { + name: "with fix", + filepath: "./mock_WithFix_test.go", + expectedPackage: "package issue845_test", + }, + { + name: "without fix", + filepath: "./mock_WithoutFix_test.go", + expectedPackage: "package issue845", + }, + } { + t.Run( + tt.name, + func(t *testing.T) { + path := pathlib.NewPath(tt.filepath) + bytes, err := path.ReadFile() + require.NoError(t, err) + fileString := string(bytes) + assert.True(t, strings.Contains(fileString, tt.expectedPackage)) + }, + ) + } +} diff --git a/pkg/fixtures/issue845/mock_WithFix_test.go b/pkg/fixtures/issue845/mock_WithFix_test.go new file mode 100644 index 00000000..94c06ac7 --- /dev/null +++ b/pkg/fixtures/issue845/mock_WithFix_test.go @@ -0,0 +1,77 @@ +// Code generated by mockery. DO NOT EDIT. + +package issue845_test + +import mock "github.com/stretchr/testify/mock" + +// WithFix is an autogenerated mock type for the Interface type +type WithFix struct { + mock.Mock +} + +type WithFix_Expecter struct { + mock *mock.Mock +} + +func (_m *WithFix) EXPECT() *WithFix_Expecter { + return &WithFix_Expecter{mock: &_m.Mock} +} + +// Foo provides a mock function with given fields: +func (_m *WithFix) Foo() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Foo") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// WithFix_Foo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Foo' +type WithFix_Foo_Call struct { + *mock.Call +} + +// Foo is a helper method to define mock.On call +func (_e *WithFix_Expecter) Foo() *WithFix_Foo_Call { + return &WithFix_Foo_Call{Call: _e.mock.On("Foo")} +} + +func (_c *WithFix_Foo_Call) Run(run func()) *WithFix_Foo_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *WithFix_Foo_Call) Return(_a0 string) *WithFix_Foo_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *WithFix_Foo_Call) RunAndReturn(run func() string) *WithFix_Foo_Call { + _c.Call.Return(run) + return _c +} + +// NewWithFix creates a new instance of WithFix. 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 NewWithFix(t interface { + mock.TestingT + Cleanup(func()) +}) *WithFix { + mock := &WithFix{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/fixtures/issue845/mock_WithoutFix_test.go b/pkg/fixtures/issue845/mock_WithoutFix_test.go new file mode 100644 index 00000000..dd1adff4 --- /dev/null +++ b/pkg/fixtures/issue845/mock_WithoutFix_test.go @@ -0,0 +1,77 @@ +// Code generated by mockery. DO NOT EDIT. + +package issue845 + +import mock "github.com/stretchr/testify/mock" + +// WithoutFix is an autogenerated mock type for the Interface type +type WithoutFix struct { + mock.Mock +} + +type WithoutFix_Expecter struct { + mock *mock.Mock +} + +func (_m *WithoutFix) EXPECT() *WithoutFix_Expecter { + return &WithoutFix_Expecter{mock: &_m.Mock} +} + +// Foo provides a mock function with given fields: +func (_m *WithoutFix) Foo() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Foo") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// WithoutFix_Foo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Foo' +type WithoutFix_Foo_Call struct { + *mock.Call +} + +// Foo is a helper method to define mock.On call +func (_e *WithoutFix_Expecter) Foo() *WithoutFix_Foo_Call { + return &WithoutFix_Foo_Call{Call: _e.mock.On("Foo")} +} + +func (_c *WithoutFix_Foo_Call) Run(run func()) *WithoutFix_Foo_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *WithoutFix_Foo_Call) Return(_a0 string) *WithoutFix_Foo_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *WithoutFix_Foo_Call) RunAndReturn(run func() string) *WithoutFix_Foo_Call { + _c.Call.Return(run) + return _c +} + +// NewWithoutFix creates a new instance of WithoutFix. 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 NewWithoutFix(t interface { + mock.TestingT + Cleanup(func()) +}) *WithoutFix { + mock := &WithoutFix{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/generator.go b/pkg/generator.go index 4f600c78..42eb14a4 100644 --- a/pkg/generator.go +++ b/pkg/generator.go @@ -55,10 +55,11 @@ type GeneratorConfig struct { DisableVersionString bool Exported bool InPackage bool + Issue845Fix bool KeepTree bool Note string MockBuildTags string - PackageName string + Outpkg string PackageNamePrefix string StructName string UnrollVariadic bool @@ -84,12 +85,14 @@ type Generator struct { // NewGenerator builds a Generator. func NewGenerator(ctx context.Context, c GeneratorConfig, iface *Interface, pkg string) *Generator { - if pkg == "" { + if c.Issue845Fix { + pkg = c.Outpkg + } else if pkg == "" { pkg = DetermineOutputPackageName( iface.FileName, iface.Pkg.Name(), c.PackageNamePrefix, - c.PackageName, + c.Outpkg, c.KeepTree, c.InPackage, ) @@ -418,8 +421,20 @@ func (g *Generator) generateImports(ctx context.Context) { // GeneratePrologue generates the prologue of the mock. func (g *Generator) GeneratePrologue(ctx context.Context, pkg string) { g.populateImports(ctx) - if g.config.InPackage { - g.printf("package %s\n\n", g.iface.Pkg.Name()) + + if !g.config.Issue845Fix { + logging.WarnDeprecated( + ctx, + "issue-845-fix must be set to True to remove this warning. Visit the link for more details.", + map[string]any{ + "url": logging.DocsURL("/deprecations/#issue-845-fix"), + }, + ) + if g.config.InPackage { + g.printf("package %s\n\n", g.iface.Pkg.Name()) + } else { + g.printf("package %v\n\n", pkg) + } } else { g.printf("package %v\n\n", pkg) } diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 4a9abf0c..ca266758 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -1,6 +1,7 @@ package logging import ( + "context" "errors" "fmt" "os" @@ -88,3 +89,25 @@ func GetLogger(levelStr string) (zerolog.Logger, error) { return log, nil } + +func Warn(ctx context.Context, prefix string, message string, fields map[string]any) { + log := zerolog.Ctx(ctx) + event := log.Warn() + if fields != nil { + event = event.Fields(fields) + } + event.Msgf("%s: %s", prefix, message) +} + +func Info(ctx context.Context, prefix string, message string, fields map[string]any) { + log := zerolog.Ctx(ctx) + event := log.Info() + if fields != nil { + event = event.Fields(fields) + } + event.Msgf("%s: %s", prefix, message) +} + +func WarnDeprecated(ctx context.Context, message string, fields map[string]any) { + Warn(ctx, "DEPRECATION", message, fields) +} diff --git a/pkg/outputter.go b/pkg/outputter.go index c1948554..e3c4d978 100644 --- a/pkg/outputter.go +++ b/pkg/outputter.go @@ -332,10 +332,11 @@ func (m *Outputter) Generate(ctx context.Context, iface *Interface) error { DisableVersionString: interfaceConfig.DisableVersionString, Exported: interfaceConfig.Exported, InPackage: interfaceConfig.InPackage, + Issue845Fix: interfaceConfig.Issue845Fix, KeepTree: interfaceConfig.KeepTree, Note: interfaceConfig.Note, MockBuildTags: interfaceConfig.MockBuildTags, - PackageName: interfaceConfig.Outpkg, + Outpkg: interfaceConfig.Outpkg, PackageNamePrefix: interfaceConfig.Packageprefix, StructName: interfaceConfig.MockName, UnrollVariadic: interfaceConfig.UnrollVariadic, diff --git a/pkg/walker.go b/pkg/walker.go index bf051579..6d290efd 100644 --- a/pkg/walker.go +++ b/pkg/walker.go @@ -183,7 +183,7 @@ func (v *GeneratorVisitor) VisitWalk(ctx context.Context, iface *Interface) erro KeepTree: v.config.KeepTree, Note: v.config.Note, MockBuildTags: v.config.MockBuildTags, - PackageName: v.config.PackageName, + Outpkg: v.config.PackageName, PackageNamePrefix: v.config.PackageNamePrefix, StructName: v.config.StructName, UnrollVariadic: v.config.UnrollVariadic,