Add -stub flag to stub func implementation (#132)
When a mock is generated with the flag enabled, it introduces the following changes: - Does not panic on calling the method without a mock implementation. - Return zero values iff the implementation is not provided and the method has return parameters. Co-authored-by: Scott Leuthaeuser <scott_leuthaeuser@homedepot.com>
This commit is contained in:
parent
24883c20a6
commit
83ab8dd79f
4
main.go
4
main.go
@ -17,6 +17,7 @@ type userFlags struct {
|
|||||||
outFile string
|
outFile string
|
||||||
pkgName string
|
pkgName string
|
||||||
formatter string
|
formatter string
|
||||||
|
stubImpl bool
|
||||||
args []string
|
args []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +26,8 @@ func main() {
|
|||||||
flag.StringVar(&flags.outFile, "out", "", "output file (default stdout)")
|
flag.StringVar(&flags.outFile, "out", "", "output file (default stdout)")
|
||||||
flag.StringVar(&flags.pkgName, "pkg", "", "package name (default will infer)")
|
flag.StringVar(&flags.pkgName, "pkg", "", "package name (default will infer)")
|
||||||
flag.StringVar(&flags.formatter, "fmt", "", "go pretty-printer: gofmt (default) or goimports")
|
flag.StringVar(&flags.formatter, "fmt", "", "go pretty-printer: gofmt (default) or goimports")
|
||||||
|
flag.BoolVar(&flags.stubImpl, "stubImpl", false,
|
||||||
|
"return zero values when no mock implementation is provided, do not panic")
|
||||||
|
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Println(`moq [flags] source-dir interface [interface2 [interface3 [...]]]`)
|
fmt.Println(`moq [flags] source-dir interface [interface2 [interface3 [...]]]`)
|
||||||
@ -59,6 +62,7 @@ func run(flags userFlags) error {
|
|||||||
SrcDir: srcDir,
|
SrcDir: srcDir,
|
||||||
PkgName: flags.pkgName,
|
PkgName: flags.pkgName,
|
||||||
Formatter: flags.formatter,
|
Formatter: flags.formatter,
|
||||||
|
StubImpl: flags.stubImpl,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -24,6 +24,7 @@ type Mocker struct {
|
|||||||
pkgName string
|
pkgName string
|
||||||
pkgPath string
|
pkgPath string
|
||||||
fmter func(src []byte) ([]byte, error)
|
fmter func(src []byte) ([]byte, error)
|
||||||
|
stubImpl bool
|
||||||
|
|
||||||
imports map[string]bool
|
imports map[string]bool
|
||||||
}
|
}
|
||||||
@ -34,6 +35,7 @@ type Config struct {
|
|||||||
SrcDir string
|
SrcDir string
|
||||||
PkgName string
|
PkgName string
|
||||||
Formatter string
|
Formatter string
|
||||||
|
StubImpl bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New makes a new Mocker for the specified package directory.
|
// New makes a new Mocker for the specified package directory.
|
||||||
@ -69,6 +71,7 @@ func New(conf Config) (*Mocker, error) {
|
|||||||
pkgName: pkgName,
|
pkgName: pkgName,
|
||||||
pkgPath: pkgPath,
|
pkgPath: pkgPath,
|
||||||
fmter: fmter,
|
fmter: fmter,
|
||||||
|
stubImpl: conf.StubImpl,
|
||||||
imports: make(map[string]bool),
|
imports: make(map[string]bool),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -107,6 +110,7 @@ func (m *Mocker) Mock(w io.Writer, names ...string) error {
|
|||||||
doc := doc{
|
doc := doc{
|
||||||
PackageName: m.pkgName,
|
PackageName: m.pkgName,
|
||||||
Imports: moqImports,
|
Imports: moqImports,
|
||||||
|
StubImpl: m.stubImpl,
|
||||||
}
|
}
|
||||||
|
|
||||||
mocksMethods := false
|
mocksMethods := false
|
||||||
@ -246,6 +250,7 @@ type doc struct {
|
|||||||
SourcePackagePrefix string
|
SourcePackagePrefix string
|
||||||
Objects []obj
|
Objects []obj
|
||||||
Imports []string
|
Imports []string
|
||||||
|
StubImpl bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type obj struct {
|
type obj struct {
|
||||||
@ -275,7 +280,7 @@ func (m *method) ArgCallList() string {
|
|||||||
return strings.Join(params, ", ")
|
return strings.Join(params, ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *method) ReturnArglist() string {
|
func (m *method) ReturnArgTypeList() string {
|
||||||
params := make([]string, len(m.Returns))
|
params := make([]string, len(m.Returns))
|
||||||
for i, p := range m.Returns {
|
for i, p := range m.Returns {
|
||||||
params[i] = p.TypeString()
|
params[i] = p.TypeString()
|
||||||
@ -286,6 +291,14 @@ func (m *method) ReturnArglist() string {
|
|||||||
return strings.Join(params, ", ")
|
return strings.Join(params, ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *method) ReturnArgNameList() string {
|
||||||
|
params := make([]string, len(m.Returns))
|
||||||
|
for i, p := range m.Returns {
|
||||||
|
params[i] = p.Name
|
||||||
|
}
|
||||||
|
return strings.Join(params, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
type param struct {
|
type param struct {
|
||||||
Name string
|
Name string
|
||||||
Type string
|
Type string
|
||||||
|
@ -284,23 +284,19 @@ func TestNothingToReturn(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestChannelNames(t *testing.T) {
|
func TestChannelNames(t *testing.T) {
|
||||||
m, err := New(Config{SrcDir: "testpackages/channels"})
|
m, err := New(Config{SrcDir: "testpackages/channels", StubImpl: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("moq.New: %s", err)
|
t.Fatalf("moq.New: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
err = m.Mock(&buf, "Queuer")
|
if err = m.Mock(&buf, "Queuer"); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Errorf("m.Mock: %s", err)
|
t.Errorf("m.Mock: %s", err)
|
||||||
}
|
}
|
||||||
s := buf.String()
|
|
||||||
var strs = []string{
|
golden := filepath.Join("testpackages/channels", "queuer_moq.golden.go")
|
||||||
"func (mock *QueuerMock) Sub(topic string) (<-chan Queue, error)",
|
if err := matchGoldenFile(golden, buf.Bytes()); err != nil {
|
||||||
}
|
t.Errorf("check golden file: %s", err)
|
||||||
for _, str := range strs {
|
|
||||||
if !strings.Contains(s, str) {
|
|
||||||
t.Errorf("expected but missing: \"%s\"", str)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ var moqTemplate = `// Code generated by moq; DO NOT EDIT.
|
|||||||
|
|
||||||
package {{.PackageName}}
|
package {{.PackageName}}
|
||||||
{{- $sourcePackagePrefix := .SourcePackagePrefix}}
|
{{- $sourcePackagePrefix := .SourcePackagePrefix}}
|
||||||
|
{{- $stubImpl := .StubImpl}}
|
||||||
|
|
||||||
import (
|
import (
|
||||||
{{- range .Imports }}
|
{{- range .Imports }}
|
||||||
@ -29,7 +30,7 @@ var _ {{$sourcePackagePrefix}}{{.InterfaceName}} = &{{.MockName}}{}
|
|||||||
//
|
//
|
||||||
// // make and configure a mocked {{$sourcePackagePrefix}}{{.InterfaceName}}
|
// // make and configure a mocked {{$sourcePackagePrefix}}{{.InterfaceName}}
|
||||||
// mocked{{.InterfaceName}} := &{{.MockName}}{ {{ range .Methods }}
|
// mocked{{.InterfaceName}} := &{{.MockName}}{ {{ range .Methods }}
|
||||||
// {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} {
|
// {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArgTypeList}} {
|
||||||
// panic("mock out the {{.Name}} method")
|
// panic("mock out the {{.Name}} method")
|
||||||
// },{{- end }}
|
// },{{- end }}
|
||||||
// }
|
// }
|
||||||
@ -41,7 +42,7 @@ var _ {{$sourcePackagePrefix}}{{.InterfaceName}} = &{{.MockName}}{}
|
|||||||
type {{.MockName}} 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 }}) {{.ReturnArgTypeList}}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
// calls tracks calls to the methods.
|
// calls tracks calls to the methods.
|
||||||
calls struct {
|
calls struct {
|
||||||
@ -61,10 +62,12 @@ type {{.MockName}} struct {
|
|||||||
}
|
}
|
||||||
{{ range .Methods }}
|
{{ range .Methods }}
|
||||||
// {{.Name}} calls {{.Name}}Func.
|
// {{.Name}} calls {{.Name}}Func.
|
||||||
func (mock *{{$obj.MockName}}) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} {
|
func (mock *{{$obj.MockName}}) {{.Name}}({{.Arglist}}) {{.ReturnArgTypeList}} {
|
||||||
|
{{- if not $stubImpl }}
|
||||||
if mock.{{.Name}}Func == nil {
|
if mock.{{.Name}}Func == nil {
|
||||||
panic("{{$obj.MockName}}.{{.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")
|
||||||
}
|
}
|
||||||
|
{{- end }}
|
||||||
callInfo := struct {
|
callInfo := struct {
|
||||||
{{- range .Params }}
|
{{- range .Params }}
|
||||||
{{ .Name | Exported }} {{ .Type }}
|
{{ .Name | Exported }} {{ .Type }}
|
||||||
@ -77,9 +80,24 @@ func (mock *{{$obj.MockName}}) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} {
|
|||||||
mock.lock{{.Name}}.Lock()
|
mock.lock{{.Name}}.Lock()
|
||||||
mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo)
|
mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo)
|
||||||
mock.lock{{.Name}}.Unlock()
|
mock.lock{{.Name}}.Unlock()
|
||||||
{{- if .ReturnArglist }}
|
{{- if .Returns }}
|
||||||
|
{{- if $stubImpl }}
|
||||||
|
if mock.{{.Name}}Func == nil {
|
||||||
|
var (
|
||||||
|
{{- range .Returns }}
|
||||||
|
{{.Name}} {{.Type}}
|
||||||
|
{{- end }}
|
||||||
|
)
|
||||||
|
return {{.ReturnArgNameList}}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
return mock.{{.Name}}Func({{.ArgCallList}})
|
return mock.{{.Name}}Func({{.ArgCallList}})
|
||||||
{{- else }}
|
{{- else }}
|
||||||
|
{{- if $stubImpl }}
|
||||||
|
if mock.{{.Name}}Func == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
mock.{{.Name}}Func({{.ArgCallList}})
|
mock.{{.Name}}Func({{.ArgCallList}})
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,5 @@ type Queue []string
|
|||||||
// Queuer provides a channel example.
|
// Queuer provides a channel example.
|
||||||
type Queuer interface {
|
type Queuer interface {
|
||||||
Sub(topic string) (<-chan Queue, error)
|
Sub(topic string) (<-chan Queue, error)
|
||||||
|
Unsub(topic string)
|
||||||
}
|
}
|
||||||
|
120
pkg/moq/testpackages/channels/queuer_moq.golden.go
Normal file
120
pkg/moq/testpackages/channels/queuer_moq.golden.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// Code generated by moq; DO NOT EDIT.
|
||||||
|
// github.com/matryer/moq
|
||||||
|
|
||||||
|
package channels
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ensure, that QueuerMock does implement Queuer.
|
||||||
|
// If this is not the case, regenerate this file with moq.
|
||||||
|
var _ Queuer = &QueuerMock{}
|
||||||
|
|
||||||
|
// QueuerMock is a mock implementation of Queuer.
|
||||||
|
//
|
||||||
|
// func TestSomethingThatUsesQueuer(t *testing.T) {
|
||||||
|
//
|
||||||
|
// // make and configure a mocked Queuer
|
||||||
|
// mockedQueuer := &QueuerMock{
|
||||||
|
// SubFunc: func(topic string) (<-chan Queue, error) {
|
||||||
|
// panic("mock out the Sub method")
|
||||||
|
// },
|
||||||
|
// UnsubFunc: func(topic string) {
|
||||||
|
// panic("mock out the Unsub method")
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // use mockedQueuer in code that requires Queuer
|
||||||
|
// // and then make assertions.
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
type QueuerMock struct {
|
||||||
|
// SubFunc mocks the Sub method.
|
||||||
|
SubFunc func(topic string) (<-chan Queue, error)
|
||||||
|
|
||||||
|
// UnsubFunc mocks the Unsub method.
|
||||||
|
UnsubFunc func(topic string)
|
||||||
|
|
||||||
|
// calls tracks calls to the methods.
|
||||||
|
calls struct {
|
||||||
|
// Sub holds details about calls to the Sub method.
|
||||||
|
Sub []struct {
|
||||||
|
// Topic is the topic argument value.
|
||||||
|
Topic string
|
||||||
|
}
|
||||||
|
// Unsub holds details about calls to the Unsub method.
|
||||||
|
Unsub []struct {
|
||||||
|
// Topic is the topic argument value.
|
||||||
|
Topic string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lockSub sync.RWMutex
|
||||||
|
lockUnsub sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub calls SubFunc.
|
||||||
|
func (mock *QueuerMock) Sub(topic string) (<-chan Queue, error) {
|
||||||
|
callInfo := struct {
|
||||||
|
Topic string
|
||||||
|
}{
|
||||||
|
Topic: topic,
|
||||||
|
}
|
||||||
|
mock.lockSub.Lock()
|
||||||
|
mock.calls.Sub = append(mock.calls.Sub, callInfo)
|
||||||
|
mock.lockSub.Unlock()
|
||||||
|
if mock.SubFunc == nil {
|
||||||
|
var (
|
||||||
|
out1 <-chan Queue
|
||||||
|
out2 error
|
||||||
|
)
|
||||||
|
return out1, out2
|
||||||
|
}
|
||||||
|
return mock.SubFunc(topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubCalls gets all the calls that were made to Sub.
|
||||||
|
// Check the length with:
|
||||||
|
// len(mockedQueuer.SubCalls())
|
||||||
|
func (mock *QueuerMock) SubCalls() []struct {
|
||||||
|
Topic string
|
||||||
|
} {
|
||||||
|
var calls []struct {
|
||||||
|
Topic string
|
||||||
|
}
|
||||||
|
mock.lockSub.RLock()
|
||||||
|
calls = mock.calls.Sub
|
||||||
|
mock.lockSub.RUnlock()
|
||||||
|
return calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsub calls UnsubFunc.
|
||||||
|
func (mock *QueuerMock) Unsub(topic string) {
|
||||||
|
callInfo := struct {
|
||||||
|
Topic string
|
||||||
|
}{
|
||||||
|
Topic: topic,
|
||||||
|
}
|
||||||
|
mock.lockUnsub.Lock()
|
||||||
|
mock.calls.Unsub = append(mock.calls.Unsub, callInfo)
|
||||||
|
mock.lockUnsub.Unlock()
|
||||||
|
if mock.UnsubFunc == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mock.UnsubFunc(topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsubCalls gets all the calls that were made to Unsub.
|
||||||
|
// Check the length with:
|
||||||
|
// len(mockedQueuer.UnsubCalls())
|
||||||
|
func (mock *QueuerMock) UnsubCalls() []struct {
|
||||||
|
Topic string
|
||||||
|
} {
|
||||||
|
var calls []struct {
|
||||||
|
Topic string
|
||||||
|
}
|
||||||
|
mock.lockUnsub.RLock()
|
||||||
|
calls = mock.calls.Unsub
|
||||||
|
mock.lockUnsub.RUnlock()
|
||||||
|
return calls
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user