From 1206bf1e2aadf664e4f61b084ce37761bbbe9d95 Mon Sep 17 00:00:00 2001 From: Suhas Karanth Date: Tue, 5 Nov 2019 13:13:49 +0530 Subject: [PATCH] Allow aliasing interface name (#110) Implementation based on #57. --- README.md | 4 +++- main.go | 2 ++ pkg/moq/moq.go | 19 ++++++++++++++++--- pkg/moq/moq_test.go | 33 +++++++++++++++++++++++++++++++++ pkg/moq/template.go | 30 +++++++++++++++--------------- 5 files changed, 69 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 69961bc..5327c44 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ moq [flags] destination interface [interface2 [interface3 [...]]] output file (default stdout) -pkg string package name (default will infer) +Specifying an alias for the mock is also supported with the format 'interface:alias' +Ex: moq -pkg different . MyInterface:MyMock ``` In a command line: @@ -63,7 +65,7 @@ In this example, Moq generated the `EmailSenderMock` type: ```go func TestCompleteSignup(t *testing.T) { - var sentTo string + var sentTo string mockedEmailSender = &EmailSenderMock{ SendFunc: func(to, subject, body string) error { diff --git a/main.go b/main.go index 072861c..f3f7e08 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,8 @@ func main() { flag.Usage = func() { fmt.Println(`moq [flags] destination interface [interface2 [interface3 [...]]]`) flag.PrintDefaults() + fmt.Println(`Specifying an alias for the mock is also supported with the format 'interface:alias'`) + fmt.Println(`Ex: moq -pkg different . MyInterface:MyMock`) } flag.Parse() args := flag.Args() diff --git a/pkg/moq/moq.go b/pkg/moq/moq.go index f57880a..971c942 100644 --- a/pkg/moq/moq.go +++ b/pkg/moq/moq.go @@ -126,8 +126,8 @@ func pkgInDir(pkgName, dir string) bool { } // Mock generates a mock for the specified interface name. -func (m *Mocker) Mock(w io.Writer, name ...string) error { - if len(name) == 0 { +func (m *Mocker) Mock(w io.Writer, names ...string) error { + if len(names) == 0 { return errors.New("must specify one interface") } @@ -139,7 +139,8 @@ func (m *Mocker) Mock(w io.Writer, name ...string) error { mocksMethods := false tpkg := m.srcPkg.Types - for _, n := range name { + for _, name := range names { + n, mockName := parseInterfaceName(name) iface := tpkg.Scope().Lookup(n) if iface == nil { return fmt.Errorf("cannot find interface %s", n) @@ -150,6 +151,7 @@ func (m *Mocker) Mock(w io.Writer, name ...string) error { iiface := iface.Type().Underlying().(*types.Interface).Complete() obj := obj{ InterfaceName: n, + MockName: mockName, } for i := 0; i < iiface.NumMethods(); i++ { mocksMethods = true @@ -248,6 +250,16 @@ func pkgInfoFromPath(src string, mode packages.LoadMode) (*packages.Package, err return pkgs[0], nil } +func parseInterfaceName(name string) (ifaceName, mockName string) { + parts := strings.SplitN(name, ":", 2) + ifaceName = parts[0] + mockName = ifaceName + "Mock" + if len(parts) == 2 { + mockName = parts[1] + } + return +} + type doc struct { PackageName string SourcePackagePrefix string @@ -257,6 +269,7 @@ type doc struct { type obj struct { InterfaceName string + MockName string Methods []*method } type method struct { diff --git a/pkg/moq/moq_test.go b/pkg/moq/moq_test.go index fe149e6..aa416ab 100644 --- a/pkg/moq/moq_test.go +++ b/pkg/moq/moq_test.go @@ -76,6 +76,39 @@ func TestMoqWithStaticCheck(t *testing.T) { } } +func TestMoqWithAlias(t *testing.T) { + m, err := New("testpackages/example", "") + if err != nil { + t.Fatalf("moq.New: %s", err) + } + var buf bytes.Buffer + err = m.Mock(&buf, "PersonStore:AnotherPersonStoreMock") + if err != nil { + t.Errorf("m.Mock: %s", err) + } + s := buf.String() + // assertions of things that should be mentioned + var strs = []string{ + "package example", + "type AnotherPersonStoreMock struct", + "CreateFunc func(ctx context.Context, person *Person, confirm bool) error", + "GetFunc func(ctx context.Context, id string) (*Person, error)", + "func (mock *AnotherPersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error", + "func (mock *AnotherPersonStoreMock) Get(ctx context.Context, id string) (*Person, error)", + "panic(\"AnotherPersonStoreMock.CreateFunc: method is nil but PersonStore.Create was just called\")", + "panic(\"AnotherPersonStoreMock.GetFunc: method is nil but PersonStore.Get was just called\")", + "lockAnotherPersonStoreMockGet.Lock()", + "mock.calls.Get = append(mock.calls.Get, callInfo)", + "lockAnotherPersonStoreMockGet.Unlock()", + "// ID is the id argument value", + } + for _, str := range strs { + if !strings.Contains(s, str) { + t.Errorf("expected but missing: \"%s\"", str) + } + } +} + func TestMoqExplicitPackage(t *testing.T) { m, err := New("testpackages/example", "different") if err != nil { diff --git a/pkg/moq/template.go b/pkg/moq/template.go index a3b1984..243559c 100644 --- a/pkg/moq/template.go +++ b/pkg/moq/template.go @@ -19,30 +19,30 @@ import ( {{ range $i, $obj := .Objects -}} var ( {{- range .Methods }} - lock{{$obj.InterfaceName}}Mock{{.Name}} sync.RWMutex + lock{{$obj.MockName}}{{.Name}} sync.RWMutex {{- end }} ) -// Ensure, that {{.InterfaceName}}Mock does implement {{.InterfaceName}}. +// Ensure, that {{.MockName}} does implement {{.InterfaceName}}. // If this is not the case, regenerate this file with moq. -var _ {{$sourcePackagePrefix}}{{.InterfaceName}} = &{{.InterfaceName}}Mock{} +var _ {{$sourcePackagePrefix}}{{.InterfaceName}} = &{{.MockName}}{} -// {{.InterfaceName}}Mock is a mock implementation of {{.InterfaceName}}. +// {{.MockName}} is a mock implementation of {{$sourcePackagePrefix}}{{.InterfaceName}}. // // func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) { // -// // make and configure a mocked {{.InterfaceName}} -// mocked{{.InterfaceName}} := &{{.InterfaceName}}Mock{ {{ range .Methods }} +// // make and configure a mocked {{$sourcePackagePrefix}}{{.InterfaceName}} +// mocked{{.InterfaceName}} := &{{.MockName}}{ {{ range .Methods }} // {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} { // panic("mock out the {{.Name}} method") // },{{- end }} // } // -// // use mocked{{.InterfaceName}} in code that requires {{.InterfaceName}} +// // use mocked{{.InterfaceName}} in code that requires {{$sourcePackagePrefix}}{{.InterfaceName}} // // and then make assertions. // // } -type {{.InterfaceName}}Mock struct { +type {{.MockName}} struct { {{- range .Methods }} // {{.Name}}Func mocks the {{.Name}} method. {{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}} @@ -62,9 +62,9 @@ type {{.InterfaceName}}Mock struct { } {{ range .Methods }} // {{.Name}} calls {{.Name}}Func. -func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} { +func (mock *{{$obj.MockName}}) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} { if mock.{{.Name}}Func == nil { - panic("{{$obj.InterfaceName}}Mock.{{.Name}}Func: method is nil but {{$obj.InterfaceName}}.{{.Name}} was just called") + panic("{{$obj.MockName}}.{{.Name}}Func: method is nil but {{$obj.InterfaceName}}.{{.Name}} was just called") } callInfo := struct { {{- range .Params }} @@ -75,9 +75,9 @@ func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist {{ .Name | Exported }}: {{ .Name }}, {{- end }} } - lock{{$obj.InterfaceName}}Mock{{.Name}}.Lock() + lock{{$obj.MockName}}{{.Name}}.Lock() mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo) - lock{{$obj.InterfaceName}}Mock{{.Name}}.Unlock() + lock{{$obj.MockName}}{{.Name}}.Unlock() {{- if .ReturnArglist }} return mock.{{.Name}}Func({{.ArgCallList}}) {{- else }} @@ -88,7 +88,7 @@ func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist // {{.Name}}Calls gets all the calls that were made to {{.Name}}. // Check the length with: // len(mocked{{$obj.InterfaceName}}.{{.Name}}Calls()) -func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}Calls() []struct { +func (mock *{{$obj.MockName}}) {{.Name}}Calls() []struct { {{- range .Params }} {{ .Name | Exported }} {{ .Type }} {{- end }} @@ -98,9 +98,9 @@ func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}Calls() []struct { {{ .Name | Exported }} {{ .Type }} {{- end }} } - lock{{$obj.InterfaceName}}Mock{{.Name}}.RLock() + lock{{$obj.MockName}}{{.Name}}.RLock() calls = mock.calls.{{.Name}} - lock{{$obj.InterfaceName}}Mock{{.Name}}.RUnlock() + lock{{$obj.MockName}}{{.Name}}.RUnlock() return calls } {{ end -}}