add skip-ensure flag to avoid import cycle (#140)
For mocks generated outside of the tested package with tests lives inside the same package as the tested code (i.e. pkg_test not used) --skip-ensure suppresses import of the source pkg https://github.com/matryer/moq/issues/139 fix typo in readme
This commit is contained in:
parent
a69ca93dec
commit
be64288727
@ -33,6 +33,9 @@ moq [flags] source-dir interface [interface2 [interface3 [...]]]
|
|||||||
package name (default will infer)
|
package name (default will infer)
|
||||||
-stub
|
-stub
|
||||||
return zero values when no mock implementation is provided, do not panic
|
return zero values when no mock implementation is provided, do not panic
|
||||||
|
-skip-ensure
|
||||||
|
suppress mock implementation check, avoid import cycle if mocks generated outside of the tested package
|
||||||
|
|
||||||
Specifying an alias for the mock is also supported with the format 'interface:alias'
|
Specifying an alias for the mock is also supported with the format 'interface:alias'
|
||||||
Ex: moq -pkg different . MyInterface:MyMock
|
Ex: moq -pkg different . MyInterface:MyMock
|
||||||
```
|
```
|
||||||
|
22
main.go
22
main.go
@ -17,11 +17,12 @@ import (
|
|||||||
var version string
|
var version string
|
||||||
|
|
||||||
type userFlags struct {
|
type userFlags struct {
|
||||||
outFile string
|
outFile string
|
||||||
pkgName string
|
pkgName string
|
||||||
formatter string
|
formatter string
|
||||||
stubImpl bool
|
stubImpl bool
|
||||||
args []string
|
skipEnsure bool
|
||||||
|
args []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -31,6 +32,8 @@ func main() {
|
|||||||
flag.StringVar(&flags.formatter, "fmt", "", "go pretty-printer: gofmt, goimports or noop (default gofmt)")
|
flag.StringVar(&flags.formatter, "fmt", "", "go pretty-printer: gofmt, goimports or noop (default gofmt)")
|
||||||
flag.BoolVar(&flags.stubImpl, "stub", false,
|
flag.BoolVar(&flags.stubImpl, "stub", false,
|
||||||
"return zero values when no mock implementation is provided, do not panic")
|
"return zero values when no mock implementation is provided, do not panic")
|
||||||
|
flag.BoolVar(&flags.skipEnsure, "skip-ensure", false,
|
||||||
|
"suppress mock implementation check, avoid import cycle if mocks generated outside of the tested package")
|
||||||
|
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Println(`moq [flags] source-dir interface [interface2 [interface3 [...]]]`)
|
fmt.Println(`moq [flags] source-dir interface [interface2 [interface3 [...]]]`)
|
||||||
@ -62,10 +65,11 @@ func run(flags userFlags) error {
|
|||||||
|
|
||||||
srcDir, args := flags.args[0], flags.args[1:]
|
srcDir, args := flags.args[0], flags.args[1:]
|
||||||
m, err := moq.New(moq.Config{
|
m, err := moq.New(moq.Config{
|
||||||
SrcDir: srcDir,
|
SrcDir: srcDir,
|
||||||
PkgName: flags.pkgName,
|
PkgName: flags.pkgName,
|
||||||
Formatter: flags.formatter,
|
Formatter: flags.formatter,
|
||||||
StubImpl: flags.stubImpl,
|
StubImpl: flags.stubImpl,
|
||||||
|
SkipEnsure: flags.skipEnsure,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -19,12 +19,13 @@ import (
|
|||||||
|
|
||||||
// Mocker can generate mock structs.
|
// Mocker can generate mock structs.
|
||||||
type Mocker struct {
|
type Mocker struct {
|
||||||
srcPkg *packages.Package
|
srcPkg *packages.Package
|
||||||
tmpl *template.Template
|
tmpl *template.Template
|
||||||
pkgName string
|
pkgName string
|
||||||
pkgPath string
|
pkgPath string
|
||||||
fmter func(src []byte) ([]byte, error)
|
fmter func(src []byte) ([]byte, error)
|
||||||
stubImpl bool
|
stubImpl bool
|
||||||
|
skipEnsure bool
|
||||||
|
|
||||||
imports map[string]bool
|
imports map[string]bool
|
||||||
}
|
}
|
||||||
@ -32,10 +33,11 @@ type Mocker struct {
|
|||||||
// Config specifies details about how interfaces should be mocked.
|
// Config specifies details about how interfaces should be mocked.
|
||||||
// SrcDir is the only field which needs be specified.
|
// SrcDir is the only field which needs be specified.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
SrcDir string
|
SrcDir string
|
||||||
PkgName string
|
PkgName string
|
||||||
Formatter string
|
Formatter string
|
||||||
StubImpl bool
|
StubImpl bool
|
||||||
|
SkipEnsure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New makes a new Mocker for the specified package directory.
|
// New makes a new Mocker for the specified package directory.
|
||||||
@ -69,13 +71,14 @@ func New(conf Config) (*Mocker, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Mocker{
|
return &Mocker{
|
||||||
tmpl: tmpl,
|
tmpl: tmpl,
|
||||||
srcPkg: srcPkg,
|
srcPkg: srcPkg,
|
||||||
pkgName: pkgName,
|
pkgName: pkgName,
|
||||||
pkgPath: pkgPath,
|
pkgPath: pkgPath,
|
||||||
fmter: fmter,
|
fmter: fmter,
|
||||||
stubImpl: conf.StubImpl,
|
stubImpl: conf.StubImpl,
|
||||||
imports: make(map[string]bool),
|
skipEnsure: conf.SkipEnsure,
|
||||||
|
imports: make(map[string]bool),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +117,7 @@ func (m *Mocker) Mock(w io.Writer, names ...string) error {
|
|||||||
PackageName: m.pkgName,
|
PackageName: m.pkgName,
|
||||||
Imports: moqImports,
|
Imports: moqImports,
|
||||||
StubImpl: m.stubImpl,
|
StubImpl: m.stubImpl,
|
||||||
|
SkipEnsure: m.skipEnsure,
|
||||||
}
|
}
|
||||||
|
|
||||||
mocksMethods := false
|
mocksMethods := false
|
||||||
@ -254,6 +258,7 @@ type doc struct {
|
|||||||
Objects []obj
|
Objects []obj
|
||||||
Imports []string
|
Imports []string
|
||||||
StubImpl bool
|
StubImpl bool
|
||||||
|
SkipEnsure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type obj struct {
|
type obj struct {
|
||||||
|
@ -172,6 +172,33 @@ func TestMoqExplicitPackageWithStaticCheck(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMoqSkipEnsure(t *testing.T) {
|
||||||
|
m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different", SkipEnsure: true})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("moq.New: %s", err)
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err = m.Mock(&buf, "PersonStore")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("m.Mock: %s", err)
|
||||||
|
}
|
||||||
|
s := buf.String()
|
||||||
|
// assertions of things that should be mentioned
|
||||||
|
var strs = []string{
|
||||||
|
"package different",
|
||||||
|
"type PersonStoreMock struct",
|
||||||
|
"CreateFunc func(ctx context.Context, person *example.Person, confirm bool) error",
|
||||||
|
"GetFunc func(ctx context.Context, id string) (*example.Person, error)",
|
||||||
|
"func (mock *PersonStoreMock) Create(ctx context.Context, person *example.Person, confirm bool) error",
|
||||||
|
"func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*example.Person, error)",
|
||||||
|
}
|
||||||
|
for _, str := range strs {
|
||||||
|
if !strings.Contains(s, str) {
|
||||||
|
t.Errorf("expected but missing: \"%s\"", str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNotCreatingEmptyDirWhenPkgIsGiven(t *testing.T) {
|
func TestNotCreatingEmptyDirWhenPkgIsGiven(t *testing.T) {
|
||||||
m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different"})
|
m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,6 +11,7 @@ var moqTemplate = `// Code generated by moq; DO NOT EDIT.
|
|||||||
package {{.PackageName}}
|
package {{.PackageName}}
|
||||||
{{- $sourcePackagePrefix := .SourcePackagePrefix}}
|
{{- $sourcePackagePrefix := .SourcePackagePrefix}}
|
||||||
{{- $stubImpl := .StubImpl}}
|
{{- $stubImpl := .StubImpl}}
|
||||||
|
{{- $skipEnsure := .SkipEnsure}}
|
||||||
|
|
||||||
import (
|
import (
|
||||||
{{- range .Imports }}
|
{{- range .Imports }}
|
||||||
@ -20,9 +21,11 @@ import (
|
|||||||
|
|
||||||
{{ range $i, $obj := .Objects -}}
|
{{ range $i, $obj := .Objects -}}
|
||||||
|
|
||||||
|
{{- if not $skipEnsure -}}
|
||||||
// Ensure, that {{.MockName}} does implement {{$sourcePackagePrefix}}{{.InterfaceName}}.
|
// Ensure, that {{.MockName}} does implement {{$sourcePackagePrefix}}{{.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}} = &{{.MockName}}{}
|
var _ {{$sourcePackagePrefix}}{{.InterfaceName}} = &{{.MockName}}{}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
// {{.MockName}} is a mock implementation of {{$sourcePackagePrefix}}{{.InterfaceName}}.
|
// {{.MockName}} is a mock implementation of {{$sourcePackagePrefix}}{{.InterfaceName}}.
|
||||||
//
|
//
|
||||||
|
@ -8,10 +8,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
lockServiceMockDoSomething sync.RWMutex
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ensure, that ServiceMock does implement Service.
|
// Ensure, that ServiceMock does implement Service.
|
||||||
// If this is not the case, regenerate this file with moq.
|
// If this is not the case, regenerate this file with moq.
|
||||||
var _ Service = &ServiceMock{}
|
var _ Service = &ServiceMock{}
|
||||||
@ -43,6 +39,7 @@ type ServiceMock struct {
|
|||||||
In1 somerepo.SomeType
|
In1 somerepo.SomeType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lockDoSomething sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoSomething calls DoSomethingFunc.
|
// DoSomething calls DoSomethingFunc.
|
||||||
@ -55,9 +52,9 @@ func (mock *ServiceMock) DoSomething(in1 somerepo.SomeType) error {
|
|||||||
}{
|
}{
|
||||||
In1: in1,
|
In1: in1,
|
||||||
}
|
}
|
||||||
lockServiceMockDoSomething.Lock()
|
mock.lockDoSomething.Lock()
|
||||||
mock.calls.DoSomething = append(mock.calls.DoSomething, callInfo)
|
mock.calls.DoSomething = append(mock.calls.DoSomething, callInfo)
|
||||||
lockServiceMockDoSomething.Unlock()
|
mock.lockDoSomething.Unlock()
|
||||||
return mock.DoSomethingFunc(in1)
|
return mock.DoSomethingFunc(in1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +67,8 @@ func (mock *ServiceMock) DoSomethingCalls() []struct {
|
|||||||
var calls []struct {
|
var calls []struct {
|
||||||
In1 somerepo.SomeType
|
In1 somerepo.SomeType
|
||||||
}
|
}
|
||||||
lockServiceMockDoSomething.RLock()
|
mock.lockDoSomething.RLock()
|
||||||
calls = mock.calls.DoSomething
|
calls = mock.calls.DoSomething
|
||||||
lockServiceMockDoSomething.RUnlock()
|
mock.lockDoSomething.RUnlock()
|
||||||
return calls
|
return calls
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user