diff --git a/mockgen/internal/tests/embed/input.go b/mockgen/internal/tests/embed/input.go new file mode 100644 index 00000000..616bf916 --- /dev/null +++ b/mockgen/internal/tests/embed/input.go @@ -0,0 +1,17 @@ +package embed + +//go:generate mockgen -embed -package embed -destination mock.go . Hoge +//go:generate mockgen -embed -destination mock/mock.go . Hoge + +type Hoge interface { + Fuga() error + mustImplementedFunction() +} + +type HogeImpl struct { + s string +} + +func (h *HogeImpl) Fuga() error { + return nil +} diff --git a/mockgen/internal/tests/embed/mock.go b/mockgen/internal/tests/embed/mock.go new file mode 100644 index 00000000..b47591a1 --- /dev/null +++ b/mockgen/internal/tests/embed/mock.go @@ -0,0 +1,61 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/golang/mock/mockgen/internal/tests/embed (interfaces: Hoge) + +// Package embed is a generated GoMock package. +package embed + +import ( + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockHoge is a mock of Hoge interface. +type MockHoge struct { + Hoge + ctrl *gomock.Controller + recorder *MockHogeMockRecorder +} + +// MockHogeMockRecorder is the mock recorder for MockHoge. +type MockHogeMockRecorder struct { + mock *MockHoge +} + +// NewMockHoge creates a new mock instance. +func NewMockHoge(ctrl *gomock.Controller) *MockHoge { + mock := &MockHoge{ctrl: ctrl} + mock.recorder = &MockHogeMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockHoge) EXPECT() *MockHogeMockRecorder { + return m.recorder +} + +// Fuga mocks base method. +func (m *MockHoge) Fuga() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Fuga") + ret0, _ := ret[0].(error) + return ret0 +} + +// Fuga indicates an expected call of Fuga. +func (mr *MockHogeMockRecorder) Fuga() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fuga", reflect.TypeOf((*MockHoge)(nil).Fuga)) +} + +// mustImplementedFunction mocks base method. +func (m *MockHoge) mustImplementedFunction() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "mustImplementedFunction") +} + +// mustImplementedFunction indicates an expected call of mustImplementedFunction. +func (mr *MockHogeMockRecorder) mustImplementedFunction() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "mustImplementedFunction", reflect.TypeOf((*MockHoge)(nil).mustImplementedFunction)) +} diff --git a/mockgen/internal/tests/embed/mock/mock.go b/mockgen/internal/tests/embed/mock/mock.go new file mode 100644 index 00000000..45d4897a --- /dev/null +++ b/mockgen/internal/tests/embed/mock/mock.go @@ -0,0 +1,62 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/golang/mock/mockgen/internal/tests/embed (interfaces: Hoge) + +// Package mock_embed is a generated GoMock package. +package mock_embed + +import ( + reflect "reflect" + + gomock "go.uber.org/mock/gomock" + embed "go.uber.org/mock/mockgen/internal/tests/embed" +) + +// MockHoge is a mock of Hoge interface. +type MockHoge struct { + embed.Hoge + ctrl *gomock.Controller + recorder *MockHogeMockRecorder +} + +// MockHogeMockRecorder is the mock recorder for MockHoge. +type MockHogeMockRecorder struct { + mock *MockHoge +} + +// NewMockHoge creates a new mock instance. +func NewMockHoge(ctrl *gomock.Controller) *MockHoge { + mock := &MockHoge{ctrl: ctrl} + mock.recorder = &MockHogeMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockHoge) EXPECT() *MockHogeMockRecorder { + return m.recorder +} + +// Fuga mocks base method. +func (m *MockHoge) Fuga() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Fuga") + ret0, _ := ret[0].(error) + return ret0 +} + +// Fuga indicates an expected call of Fuga. +func (mr *MockHogeMockRecorder) Fuga() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fuga", reflect.TypeOf((*MockHoge)(nil).Fuga)) +} + +// mustImplementedFunction mocks base method. +func (m *MockHoge) mustImplementedFunction() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "mustImplementedFunction") +} + +// mustImplementedFunction indicates an expected call of mustImplementedFunction. +func (mr *MockHogeMockRecorder) mustImplementedFunction() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "mustImplementedFunction", reflect.TypeOf((*MockHoge)(nil).mustImplementedFunction)) +} diff --git a/mockgen/internal/tests/embed/mock/mock_test.go b/mockgen/internal/tests/embed/mock/mock_test.go new file mode 100644 index 00000000..7c5d51e5 --- /dev/null +++ b/mockgen/internal/tests/embed/mock/mock_test.go @@ -0,0 +1,19 @@ +package mock_embed_test + +import ( + reflect "reflect" + "testing" + + "go.uber.org/mock/gomock" + "go.uber.org/mock/mockgen/internal/tests/embed" + mock_embed "go.uber.org/mock/mockgen/internal/tests/embed/mock" +) + +func TestEmbed(t *testing.T) { + hoge := mock_embed.NewMockHoge(gomock.NewController(t)) + et := reflect.TypeOf((*embed.Hoge)(nil)).Elem() + ht := reflect.TypeOf(hoge) + if !ht.Implements(et) { + t.Errorf("source interface has been not implemented") + } +} diff --git a/mockgen/internal/tests/embed/mock_test.go b/mockgen/internal/tests/embed/mock_test.go new file mode 100644 index 00000000..2c269521 --- /dev/null +++ b/mockgen/internal/tests/embed/mock_test.go @@ -0,0 +1,19 @@ +// This test is for when mock is same package as the source. +package embed_test + +import ( + reflect "reflect" + "testing" + + "go.uber.org/mock/gomock" + "go.uber.org/mock/mockgen/internal/tests/embed" +) + +func TestEmbed(t *testing.T) { + hoge := embed.NewMockHoge(gomock.NewController(t)) + et := reflect.TypeOf((*embed.Hoge)(nil)).Elem() + ht := reflect.TypeOf(hoge) + if !ht.Implements(et) { + t.Errorf("source interface has been not implemented") + } +} diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go index b5365de5..285b173e 100644 --- a/mockgen/mockgen.go +++ b/mockgen/mockgen.go @@ -64,6 +64,7 @@ var ( writeSourceComment = flag.Bool("write_source_comment", true, "Writes original file (source mode) or interface names (package mode) comment if true.") writeGenerateDirective = flag.Bool("write_generate_directive", false, "Add //go:generate directive to regenerate the mock") copyrightFile = flag.String("copyright_file", "", "Copyright file used to add copyright header") + embed = flag.Bool("embed", false, "Embed source interface into generated mock structure") buildConstraint = flag.String("build_constraint", "", "If non-empty, added as //go:build ") typed = flag.Bool("typed", false, "Generate Type-safe 'Return', 'Do', 'DoAndReturn' function") imports = flag.String("imports", "", "(source mode) Comma-separated name=path pairs of explicit imports to use.") @@ -411,6 +412,9 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac g.packageMap[pth] = pkgName localNames[pkgName] = true } + if *embed && pkg.Name != *packageOut { + g.packageMap[g.srcPackage] = pkg.Name + } // Ensure there is an empty line between “generated by” block and // package documentation comments to follow the recommendations: @@ -442,7 +446,7 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac } for _, intf := range pkg.Interfaces { - if err := g.GenerateMockInterface(intf, outputPackagePath); err != nil { + if err := g.GenerateMockInterface(pkg.Name, intf, outputPackagePath); err != nil { return err } } @@ -484,7 +488,7 @@ func (g *generator) formattedTypeParams(it *model.Interface, pkgOverride string) return long.String(), short.String() } -func (g *generator) GenerateMockInterface(intf *model.Interface, outputPackagePath string) error { +func (g *generator) GenerateMockInterface(pkgName string, intf *model.Interface, outputPackagePath string) error { mockType := g.mockName(intf.Name) longTp, shortTp := g.formattedTypeParams(intf, outputPackagePath) @@ -492,6 +496,13 @@ func (g *generator) GenerateMockInterface(intf *model.Interface, outputPackagePa g.p("// %v is a mock of %v interface.", mockType, intf.Name) g.p("type %v%v struct {", mockType, longTp) g.in() + if *embed { + if pkgName != *packageOut { + g.p("%v.%v", pkgName, intf.Name) + } else { + g.p("%v", intf.Name) + } + } g.p("ctrl *gomock.Controller") g.p("recorder *%vMockRecorder%v", mockType, shortTp) g.p("isgomock struct{}")