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..59e28a7a --- /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 "github.com/golang/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..c4163de5 --- /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 "github.com/golang/mock/gomock" + embed "github.com/golang/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..26743068 --- /dev/null +++ b/mockgen/internal/tests/embed/mock/mock_test.go @@ -0,0 +1,19 @@ +package mock_embed_test + +import ( + reflect "reflect" + "testing" + + "github.com/golang/mock/gomock" + "github.com/golang/mock/mockgen/internal/tests/embed" + mock_embed "github.com/golang/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..b744a442 --- /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" + + "github.com/golang/mock/gomock" + "github.com/golang/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 79cb921c..b47d9e2e 100644 --- a/mockgen/mockgen.go +++ b/mockgen/mockgen.go @@ -61,6 +61,7 @@ var ( selfPackage = flag.String("self_package", "", "The full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. This can happen if the mock's package is set to one of its inputs (usually the main one) and the output is stdio so mockgen cannot detect the final output package. Setting this flag will then tell mockgen which import to exclude.") writePkgComment = flag.Bool("write_package_comment", true, "Writes package documentation comment (godoc) if true.") copyrightFile = flag.String("copyright_file", "", "Copyright file used to add copyright header") + embed = flag.Bool("embed", false, "Embed source interface into generated mock structure") debugParser = flag.Bool("debug_parser", false, "Print out parser results only.") showVersion = flag.Bool("version", false, "Print version.") @@ -341,6 +342,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 + } if *writePkgComment { g.p("// Package %v is a generated GoMock package.", outputPkgName) @@ -362,7 +366,7 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac g.p(")") 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 } } @@ -404,7 +408,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) @@ -412,6 +416,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.out()