Allow aliasing interface name (#110)

Implementation based on #57.
This commit is contained in:
Suhas Karanth 2019-11-05 13:13:49 +05:30 committed by GitHub
parent 382bd174c0
commit 1206bf1e2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 19 deletions

View File

@ -29,6 +29,8 @@ moq [flags] destination interface [interface2 [interface3 [...]]]
output file (default stdout) output file (default stdout)
-pkg string -pkg string
package name (default will infer) 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: In a command line:
@ -63,7 +65,7 @@ In this example, Moq generated the `EmailSenderMock` type:
```go ```go
func TestCompleteSignup(t *testing.T) { func TestCompleteSignup(t *testing.T) {
var sentTo string var sentTo string
mockedEmailSender = &EmailSenderMock{ mockedEmailSender = &EmailSenderMock{
SendFunc: func(to, subject, body string) error { SendFunc: func(to, subject, body string) error {

View File

@ -30,6 +30,8 @@ func main() {
flag.Usage = func() { flag.Usage = func() {
fmt.Println(`moq [flags] destination interface [interface2 [interface3 [...]]]`) fmt.Println(`moq [flags] destination interface [interface2 [interface3 [...]]]`)
flag.PrintDefaults() 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() flag.Parse()
args := flag.Args() args := flag.Args()

View File

@ -126,8 +126,8 @@ func pkgInDir(pkgName, dir string) bool {
} }
// Mock generates a mock for the specified interface name. // Mock generates a mock for the specified interface name.
func (m *Mocker) Mock(w io.Writer, name ...string) error { func (m *Mocker) Mock(w io.Writer, names ...string) error {
if len(name) == 0 { if len(names) == 0 {
return errors.New("must specify one interface") return errors.New("must specify one interface")
} }
@ -139,7 +139,8 @@ func (m *Mocker) Mock(w io.Writer, name ...string) error {
mocksMethods := false mocksMethods := false
tpkg := m.srcPkg.Types tpkg := m.srcPkg.Types
for _, n := range name { for _, name := range names {
n, mockName := parseInterfaceName(name)
iface := tpkg.Scope().Lookup(n) iface := tpkg.Scope().Lookup(n)
if iface == nil { if iface == nil {
return fmt.Errorf("cannot find interface %s", n) 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() iiface := iface.Type().Underlying().(*types.Interface).Complete()
obj := obj{ obj := obj{
InterfaceName: n, InterfaceName: n,
MockName: mockName,
} }
for i := 0; i < iiface.NumMethods(); i++ { for i := 0; i < iiface.NumMethods(); i++ {
mocksMethods = true mocksMethods = true
@ -248,6 +250,16 @@ func pkgInfoFromPath(src string, mode packages.LoadMode) (*packages.Package, err
return pkgs[0], nil 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 { type doc struct {
PackageName string PackageName string
SourcePackagePrefix string SourcePackagePrefix string
@ -257,6 +269,7 @@ type doc struct {
type obj struct { type obj struct {
InterfaceName string InterfaceName string
MockName string
Methods []*method Methods []*method
} }
type method struct { type method struct {

View File

@ -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) { func TestMoqExplicitPackage(t *testing.T) {
m, err := New("testpackages/example", "different") m, err := New("testpackages/example", "different")
if err != nil { if err != nil {

View File

@ -19,30 +19,30 @@ import (
{{ range $i, $obj := .Objects -}} {{ range $i, $obj := .Objects -}}
var ( var (
{{- range .Methods }} {{- range .Methods }}
lock{{$obj.InterfaceName}}Mock{{.Name}} sync.RWMutex lock{{$obj.MockName}}{{.Name}} sync.RWMutex
{{- end }} {{- 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. // 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) { // func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) {
// //
// // make and configure a mocked {{.InterfaceName}} // // make and configure a mocked {{$sourcePackagePrefix}}{{.InterfaceName}}
// mocked{{.InterfaceName}} := &{{.InterfaceName}}Mock{ {{ range .Methods }} // mocked{{.InterfaceName}} := &{{.MockName}}{ {{ range .Methods }}
// {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} { // {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} {
// panic("mock out the {{.Name}} method") // panic("mock out the {{.Name}} method")
// },{{- end }} // },{{- end }}
// } // }
// //
// // use mocked{{.InterfaceName}} in code that requires {{.InterfaceName}} // // use mocked{{.InterfaceName}} in code that requires {{$sourcePackagePrefix}}{{.InterfaceName}}
// // and then make assertions. // // and then make assertions.
// //
// } // }
type {{.InterfaceName}}Mock struct { type {{.MockName}} struct {
{{- range .Methods }} {{- range .Methods }}
// {{.Name}}Func mocks the {{.Name}} method. // {{.Name}}Func mocks the {{.Name}} method.
{{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}} {{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}}
@ -62,9 +62,9 @@ type {{.InterfaceName}}Mock struct {
} }
{{ range .Methods }} {{ range .Methods }}
// {{.Name}} calls {{.Name}}Func. // {{.Name}} calls {{.Name}}Func.
func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} { func (mock *{{$obj.MockName}}) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} {
if mock.{{.Name}}Func == nil { 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 { callInfo := struct {
{{- range .Params }} {{- range .Params }}
@ -75,9 +75,9 @@ func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist
{{ .Name | Exported }}: {{ .Name }}, {{ .Name | Exported }}: {{ .Name }},
{{- end }} {{- end }}
} }
lock{{$obj.InterfaceName}}Mock{{.Name}}.Lock() lock{{$obj.MockName}}{{.Name}}.Lock()
mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo) mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo)
lock{{$obj.InterfaceName}}Mock{{.Name}}.Unlock() lock{{$obj.MockName}}{{.Name}}.Unlock()
{{- if .ReturnArglist }} {{- if .ReturnArglist }}
return mock.{{.Name}}Func({{.ArgCallList}}) return mock.{{.Name}}Func({{.ArgCallList}})
{{- else }} {{- else }}
@ -88,7 +88,7 @@ func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist
// {{.Name}}Calls gets all the calls that were made to {{.Name}}. // {{.Name}}Calls gets all the calls that were made to {{.Name}}.
// Check the length with: // Check the length with:
// len(mocked{{$obj.InterfaceName}}.{{.Name}}Calls()) // len(mocked{{$obj.InterfaceName}}.{{.Name}}Calls())
func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}Calls() []struct { func (mock *{{$obj.MockName}}) {{.Name}}Calls() []struct {
{{- range .Params }} {{- range .Params }}
{{ .Name | Exported }} {{ .Type }} {{ .Name | Exported }} {{ .Type }}
{{- end }} {{- end }}
@ -98,9 +98,9 @@ func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}Calls() []struct {
{{ .Name | Exported }} {{ .Type }} {{ .Name | Exported }} {{ .Type }}
{{- end }} {{- end }}
} }
lock{{$obj.InterfaceName}}Mock{{.Name}}.RLock() lock{{$obj.MockName}}{{.Name}}.RLock()
calls = mock.calls.{{.Name}} calls = mock.calls.{{.Name}}
lock{{$obj.InterfaceName}}Mock{{.Name}}.RUnlock() lock{{$obj.MockName}}{{.Name}}.RUnlock()
return calls return calls
} }
{{ end -}} {{ end -}}