diff --git a/README.md b/README.md index b0f06af..15ee36c 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ The mocked structure implements the interface, where each method calls the assoc * It will panic if a nil function gets called * Name arguments in the interface for a better experience * Use closured variables inside your test function to capture details about the calls to the methods -* Use `.CallsTo.Method` to track the calls +* Use `.MethodCalls()` to track the calls * Use `go:generate` to invoke the `moq` command ## License diff --git a/example/mockpersonstore_test.go b/example/mockpersonstore_test.go new file mode 100755 index 0000000..46f3338 --- /dev/null +++ b/example/mockpersonstore_test.go @@ -0,0 +1,134 @@ +package example + +// AUTOGENERATED BY MOQ - DO NOT EDIT +// github.com/matryer/moq + +import ( + "sync" + "context" +) + +var ( + lockPersonStoreMockCreate sync.RWMutex + lockPersonStoreMockGet sync.RWMutex +) + +// PersonStoreMock is a mock implementation of PersonStore. +// +// func TestSomethingThatUsesPersonStore(t *testing.T) { +// +// // make and configure a mocked PersonStore +// mockedPersonStore := &PersonStoreMock{ +// CreateFunc: func(ctx context.Context, person *Person, confirm bool) error { +// panic("TODO: mock out the Create method") +// }, +// GetFunc: func(ctx context.Context, id string) (*Person, error) { +// panic("TODO: mock out the Get method") +// }, +// } +// +// // TODO: use mockedPersonStore in code that requires PersonStore +// // and then make assertions. +// +// } +type PersonStoreMock struct { + // CreateFunc mocks the Create method. + CreateFunc func(ctx context.Context, person *Person, confirm bool) error + + // GetFunc mocks the Get method. + GetFunc func(ctx context.Context, id string) (*Person, error) + + // calls tracks calls to the methods. + calls struct { + // Create holds details about calls to the Create method. + Create []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Person is the person argument value. + Person *Person + // Confirm is the confirm argument value. + Confirm bool + } + // Get holds details about calls to the Get method. + Get []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Id is the id argument value. + Id string + } + } +} + +// Create calls CreateFunc. +func (mock *PersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error { + if mock.CreateFunc == nil { + panic("moq: PersonStoreMock.CreateFunc is nil but PersonStore.Create was just called") + } + callInfo := struct { + Ctx context.Context + Person *Person + Confirm bool + }{ + Ctx: ctx, + Person: person, + Confirm: confirm, + } + lockPersonStoreMockCreate.Lock() + mock.calls.Create = append(mock.calls.Create, callInfo) + lockPersonStoreMockCreate.Unlock() + return mock.CreateFunc(ctx, person, confirm) +} + +// CreateCalls gets all the calls that were made to Create. +// Check the length with: +// len(mockedPersonStore.CreateCalls()) +func (mock *PersonStoreMock) CreateCalls() []struct { + Ctx context.Context + Person *Person + Confirm bool + } { + var calls []struct { + Ctx context.Context + Person *Person + Confirm bool + } + lockPersonStoreMockCreate.RLock() + calls = mock.calls.Create + lockPersonStoreMockCreate.RUnlock() + return calls +} + +// Get calls GetFunc. +func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*Person, error) { + if mock.GetFunc == nil { + panic("moq: PersonStoreMock.GetFunc is nil but PersonStore.Get was just called") + } + callInfo := struct { + Ctx context.Context + Id string + }{ + Ctx: ctx, + Id: id, + } + lockPersonStoreMockGet.Lock() + mock.calls.Get = append(mock.calls.Get, callInfo) + lockPersonStoreMockGet.Unlock() + return mock.GetFunc(ctx, id) +} + +// GetCalls gets all the calls that were made to Get. +// Check the length with: +// len(mockedPersonStore.GetCalls()) +func (mock *PersonStoreMock) GetCalls() []struct { + Ctx context.Context + Id string + } { + var calls []struct { + Ctx context.Context + Id string + } + lockPersonStoreMockGet.RLock() + calls = mock.calls.Get + lockPersonStoreMockGet.RUnlock() + return calls +} diff --git a/pkg/moq/moq.go b/pkg/moq/moq.go index a006121..c4d4b8e 100644 --- a/pkg/moq/moq.go +++ b/pkg/moq/moq.go @@ -221,84 +221,3 @@ var templateFuncs = template.FuncMap{ return strings.ToUpper(s[0:1]) + s[1:] }, } - -// moqImports are the imports all moq files get. -var moqImports = []string{"sync"} - -// moqTemplate is the template for mocked code. -var moqTemplate = `package {{.PackageName}} - -// AUTOGENERATED BY MOQ -// github.com/matryer/moq - -import ( -{{- range .Imports }} - "{{.}}" -{{- end }} -) -{{ range $i, $obj := .Objects }} -// {{.InterfaceName}}Mock is a mock implementation of {{.InterfaceName}}. -// -// func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) { -// -// // make and configure a mocked {{.InterfaceName}} -// mocked{{.InterfaceName}} := &{{.InterfaceName}}Mock{ {{ range .Methods }} -// {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} { -// panic("TODO: mock out the {{.Name}} method") -// },{{- end }} -// } -// -// // TODO: use mocked{{.InterfaceName}} in code that requires {{.InterfaceName}} -// // and then make assertions. -// // -// // Use the CallsTo structure to access details about what calls were made: -// // -// // if len(mocked{{.InterfaceName}}.CallsTo.MethodFunc) != 1 { -// // t.Errorf("expected 1 call there were %d", len(mocked{{.InterfaceName}}.CallsTo.MethodFunc)) -// // } -// -// } -type {{.InterfaceName}}Mock struct { -{{- range .Methods }} - // {{.Name}}Func mocks the {{.Name}} method. - {{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}} -{{ end }} - // CallsTo tracks calls to the methods. - CallsTo struct { -{{- range .Methods }} - lock{{.Name}} sync.Mutex // protects {{ .Name }} - // {{ .Name }} holds details about calls to the {{.Name}} method. - {{ .Name }} []struct { - {{- range .Params }} - // {{ .Name | Exported }} is the {{ .Name }} argument value. - {{ .Name | Exported }} {{ .Type }} - {{- end }} - } -{{- end }} - } -} -{{ range .Methods }} -// {{.Name}} calls {{.Name}}Func. -func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} { - if mock.{{.Name}}Func == nil { - panic("moq: {{$obj.InterfaceName}}Mock.{{.Name}}Func is nil but was just called") - } - mock.CallsTo.lock{{.Name}}.Lock() - mock.CallsTo.{{.Name}} = append(mock.CallsTo.{{.Name}}, struct{ - {{- range .Params }} - {{ .Name | Exported }} {{ .Type }} - {{- end }} - }{ - {{- range .Params }} - {{ .Name | Exported }}: {{ .Name }}, - {{- end }} - }) - mock.CallsTo.lock{{.Name}}.Unlock() -{{- if .ReturnArglist }} - return mock.{{.Name}}Func({{.ArgCallList}}) -{{- else }} - mock.{{.Name}}Func({{.ArgCallList}}) -{{- end }} -} -{{ end -}} -{{ end -}}` diff --git a/pkg/moq/moq_test.go b/pkg/moq/moq_test.go index d54d70b..4188440 100644 --- a/pkg/moq/moq_test.go +++ b/pkg/moq/moq_test.go @@ -25,18 +25,17 @@ func TestMoq(t *testing.T) { "GetFunc func(ctx context.Context, id string) (*Person, error)", "func (mock *PersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error", "func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*Person, error)", - "panic(\"moq: PersonStoreMock.CreateFunc is nil but was just called\")", - "panic(\"moq: PersonStoreMock.GetFunc is nil but was just called\")", - "mock.CallsTo.lockGet.Lock()", - "mock.CallsTo.Get = append(mock.CallsTo.Get, struct{", - "mock.CallsTo.lockGet.Unlock()", + "panic(\"moq: PersonStoreMock.CreateFunc is nil but PersonStore.Create was just called\")", + "panic(\"moq: PersonStoreMock.GetFunc is nil but PersonStore.Get was just called\")", + "lockPersonStoreMockGet.Lock()", + "mock.calls.Get = append(mock.calls.Get, callInfo)", + "lockPersonStoreMockGet.Unlock()", } for _, str := range strs { if !strings.Contains(s, str) { t.Errorf("expected but missing: \"%s\"", str) } } - } func TestMoqExplicitPackage(t *testing.T) { diff --git a/pkg/moq/template.go b/pkg/moq/template.go new file mode 100644 index 0000000..4fd2747 --- /dev/null +++ b/pkg/moq/template.go @@ -0,0 +1,102 @@ +package moq + +// moqImports are the imports all moq files get. +var moqImports = []string{"sync"} + +// moqTemplate is the template for mocked code. +var moqTemplate = `package {{.PackageName}} + +// AUTOGENERATED BY MOQ - DO NOT EDIT +// github.com/matryer/moq + +import ( +{{- range .Imports }} + "{{.}}" +{{- end }} +) + +{{ range $i, $obj := .Objects -}} +var ( +{{- range .Methods }} + lock{{$obj.InterfaceName}}Mock{{.Name}} sync.RWMutex +{{- end }} +) + +// {{.InterfaceName}}Mock is a mock implementation of {{.InterfaceName}}. +// +// func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) { +// +// // make and configure a mocked {{.InterfaceName}} +// mocked{{.InterfaceName}} := &{{.InterfaceName}}Mock{ {{ range .Methods }} +// {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} { +// panic("TODO: mock out the {{.Name}} method") +// },{{- end }} +// } +// +// // TODO: use mocked{{.InterfaceName}} in code that requires {{.InterfaceName}} +// // and then make assertions. +// +// } +type {{.InterfaceName}}Mock struct { +{{- range .Methods }} + // {{.Name}}Func mocks the {{.Name}} method. + {{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}} +{{ end }} + // calls tracks calls to the methods. + calls struct { +{{- range .Methods }} + // {{ .Name }} holds details about calls to the {{.Name}} method. + {{ .Name }} []struct { + {{- range .Params }} + // {{ .Name | Exported }} is the {{ .Name }} argument value. + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } +{{- end }} + } +} +{{ range .Methods }} +// {{.Name}} calls {{.Name}}Func. +func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} { + if mock.{{.Name}}Func == nil { + panic("moq: {{$obj.InterfaceName}}Mock.{{.Name}}Func is nil but {{$obj.InterfaceName}}.{{.Name}} was just called") + } + callInfo := struct { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + }{ + {{- range .Params }} + {{ .Name | Exported }}: {{ .Name }}, + {{- end }} + } + lock{{$obj.InterfaceName}}Mock{{.Name}}.Lock() + mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo) + lock{{$obj.InterfaceName}}Mock{{.Name}}.Unlock() +{{- if .ReturnArglist }} + return mock.{{.Name}}Func({{.ArgCallList}}) +{{- else }} + mock.{{.Name}}Func({{.ArgCallList}}) +{{- end }} +} + +// {{.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 { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } { + var calls []struct { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } + lock{{$obj.InterfaceName}}Mock{{.Name}}.RLock() + calls = mock.calls.{{.Name}} + lock{{$obj.InterfaceName}}Mock{{.Name}}.RUnlock() + return calls +} +{{ end -}} +{{ end -}}` diff --git a/preview.png b/preview.png index 73a242f..8fa7a62 100644 Binary files a/preview.png and b/preview.png differ